home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-02-07 | 7.2 MB | 155,333 lines | [TEXT/MPS ] |
Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
- æKY CopyrightNotice
- æC Copyright Apple Computer, Inc. 1985-1990, All rights reserved.
- 411 - Inside Macintosh Help - MPW 3.2 Final Release.
- Friday, March 29,1991 9:00:00 AM
-
- Information source: SpInsideMacintosh 1.0 HyperCard stack.
- Pegasus 1.2.5 Hypercard Stack IM Vol VI
- Inside Macintosh Volume VI Hypercard Stack
- æKY Help
- InsideMacintoshHelp
- æC
- AboutInsideMacintoshHelp Preface UserInterfaceGuidelines
- IntroductionToSystem7.0 RoadMap WorldwideSoftwareOverview
-
-
- AliasManager FontManager QuickDraw
- AppleEventManager GraphicsDevicesManager ResourceManager
- AppleTalkManager HelpManager ScrapManager
- ColorManager ListManager ScriptManager
- ControlManager MemoryManager SCSIManager
- DataAccessManager MenuManager ShutdownManager
- DeferredTaskManager NotificationManager SlotManager
- DeskManager OSEventManager SoundManager
- DeviceManager PackageManager StartManager
- DialogManager PaletteManager TimeManager
- EditionManager PowerManager ToolboxEventManager
- EventManager PrintingManager VerticalRetraceManager
- FileManager ProcessManagement WindowManager
-
-
-
- AppleDesktopBus FloatingPointPackage SerialDrivers
- BinaryDecimalConversion GraphicsOverView SoundDriver
- ColorPickerPackage InternationalUtilities StandardFilePackage
- ColorQuickDraw MacintoshHardware SystemErrorHandler
- CompatibilityGuidelines MemoryManagement SystemResourceFile
- ControlPanels OSUtilities TextEdit
- DiskDriver PictureUtilitiesPackage ToolboxUtilities
- DiskInitialization PPCToolbox UsingAssemblyLanguage
- FinderInterface SegmentLoader
-
-
- A.ResultCodes C.SystemTraps SystemErrors
- B.MovesMemory D.GlobalVariables Glossary
-
- æKY AboutInsideMacintoshHelp
- æC
-
- ------------------------------------------------------------------------------
- Version 1.0 Final
-
- Shipped with MPW 3.2 Final and System 7.0 Final CD releases.
- Includes the latest changes to InsideMacintosh VI document.
-
- ------------------------------------------------------------------------------
- Version 1.0 B2
-
- Shipped on the ETO#3 CD release and System 7.0 B4 CD Release.
- This version has more current Volume VI information.
-
-
- ------------------------------------------------------------------------------
- Version 1.0 B1:
-
- Volume VI chapters have been added to this version which contain information
- about System 7.0, new managers and changes to previous ones.
-
- New manager chapters are:
- AppleTalk Manager
- Edition Manager
- Event Manager
- GraphicDevices Manager (Replaces the Graphic Devices chapter in Volume V)
- Help Manager
- Memory Management
- Power Manager
- PPC Toolbox
- Process Management
-
- Changed chapters are:
- Alias Manager
- Color Picker Package
- Color Quikdraw
- Control Panels
- File Manager
- FinderInterface
- Font Manager
- Notification Manager
- Palette Manager
- Resource Manager
- Slot Manager
- Sound Manager
- TextEdit
- Time Manager
-
- New/changed documentation chapters are:
- Compatibility Guidelines
- Graphics Overview
- Introduction to System 7.0
- Preface
- UserInterface Guidelines VI
- Worldwide Software Overview
-
- ------------------------------------------------------------------------------
- Version 1.0 Alpha:
-
- InsideMacintoshHelp file provides on-line documentation for the 411 project.
- This version contains all the chapters of InsideMacintosh Volumes I - V.
-
-
- æKY AliasManager
- æC
- _______________________________________________________________________________
-
- THE ALIAS MANAGER
- _______________________________________________________________________________
-
- About…the…Alias…Manager…Chapter…Volume…VI
- About…the…Alias…Manager…Volume…VI
- About…Alias…Records…Volume…VI
- Search…Strategies3.…Volume…VI
- Fast…Search
- Exhaustive…Search
- Using…the…Alias…Manager…Volume…VI
- Creating…Alias…Records
- Resolving…Alias…Records
- Resolvealias
- Matchalias
- Maintaining…Alias…Records
- Getting…Information…About…Alias…Records
- Customizing…Alias…Records
- Alias…Manager…Routines…Volume…VI
- Creating…and…Updating…Alias…Records
- Resolving…and…Reading…Alias…Records
- Filtering…Possible…Targets
- Summary…of…the…Alias…Manager…Volume…VI
- Alias…Manager…Constants
- Alias…Manager…Data…Types
- Alias…Manager…Routines…Summary
- Alias…Manager…Application-Defined…Routine
- Alias…Manager…Result…Codes
- Alias…Manager…Assembly-Language…Information
- _______________________________________________________________________________
-
-
-
- æKY About…the…Alias…Manager…Chapter…Volume…VI
- æC »About the Alias Manager Chapter Volume VI The Alias Manager
- _______________________________________________________________________________
-
- This chapter describes how your application can use the Alias Manager to
- establish and resolve alias records, which are data structures that describe
- file system objects (that is, files, directories, and volumes).
-
- You create an alias record to take a fingerprint of a file system object,
- usually a file, that you might need to locate again later. You can store the
- alias record, instead of a standard file specification, and then let the Alias
- Manager find the file again when it’s needed. The Alias Manager contains
- algorithms for locating files that have been moved, renamed, copied, or restored
- from backup.
-
- Note: The Alias Manager lets you exploit alias records. It does not directly
-
- manipulate Finder™ aliases, which are created and managed by the user through
- the Finder. The Finder Interface chapter describes Finder aliases and how
- your
- application can accommodate them.
-
- The Alias Manager is available only in system software version 7.0 or later.
- Call the Gestalt function, described in the Compatibility Guidelines chapter of
- this volume, to determine whether the Alias Manager is present.
-
- Read this chapter if you want your application to create and resolve alias
- records. You might store an alias record, for example, to identify a customized
- dictionary from within a word-processing document. When the user runs a spelling
- checker on the document, your application can ask the Alias Manager to resolve
- the record to find the correct dictionary.
-
- To use this chapter, you should be familiar with the File Manager’s conventions
- for identifying files, directories, and volumes, as described in the File
- Manager chapter in this volume.
-
- _______________________________________________________________________________
-
- æKY About…the…Alias…Manager…Volume…VI
- æC »About the Alias Manager Volume VI The Alias Manager
- _______________________________________________________________________________
-
- The Alias Manager creates and resolves alias records. The next section, “About
- Alias Records,” describes how you can use alias records.
-
- In general, you should use the Alias Manager to create an alias record whenever
- you find yourself storing a specific file description, such as filename and
- parent directory ID. The Alias Manager stores this information and more in the
- alias record, and it also provides a set of search strategies for resolving the
- record later. The search strategies are described later in this chapter in
- “Resolving Alias Records.”
-
- You can use the Alias Manager to
-
- • create alias records
-
- • resolve alias records
-
- • update alias records
-
- • get information about alias records
-
- The Alias Manager can track files and directories across volumes. If the target
- of an alias record is on an unmounted AppleShare® volume, the Alias Manager
- automatically mounts the volume when it resolves the alias. If the target object
- is on an unmounted ejectable volume, the Alias Manager prompts the user to
- insert the volume.
-
- When the Alias Manager creates an alias record, it allocates the storage, fills
- in the record, and returns a handle to it. Your application is responsible for
- storing the record and retrieving it when needed. Your application must also
- supply strategies for handling various alias-resolution problems, described in
- “Resolving Alias Records.”
-
- To help you understand and use the Alias Manager, this chapter provides
-
- • an overview of alias records
-
- • a description of how the Alias Manager resolves alias records
-
- • specific techniques for using the Alias Manager in your application
- _______________________________________________________________________________
-
- æKY About…Alias…Records…Volume…VI
- æC »About Alias Records Volume VI The Alias Manager
- _______________________________________________________________________________
-
- An alias record is a data structure that describes a file, directory, or volume.
- The record contains
-
- • location information, such as name and parent directory ID
-
- • verification information, such as creation date, file type, and creator
-
- • volume mounting information (that is, server and zone), if applicable
-
- By storing alias records, you can allow your users to create a robust connection
- to a file—that is, a connection that can survive the moving or renaming of the
- target file. The Finder in system software version 7.0, for example, stores
- alias records in aliases created by the user to represent other files or
- folders. The Edition Manager uses alias records to support data-sharing among
- separate documents. (The Finder Interface and Edition Manager chapters in this
- volume describe those features in detail.)
-
- An alias record is a reliable way to identify a file system object when your
- application is communicating with a process that might be running on a different
- machine.
-
- The creation of an alias record has no effect on the target of the record,
- except to establish a file ID if one did not previously exist for the target
- file. (See the File Manager chapter of this volume for a description of file
- IDs.)
-
- The alias record contains only two fields of public information available to
- your application. The bulk of the record is managed privately by the Alias
- Manager.
-
- TYPE AliasRecord =
- RECORD
- userType: OSType; {application’s signature}
- aliasSize: Integer; {size of record when created}
- {variable-length private data}
- END;
-
- Your application can use the userType field to store its own signature or any
- other data that fits into 4 bytes. When the Alias Manager creates an alias
- record, it stores 0 in that field.
-
- The Alias Manager stores the size of the record when it was created in the
- aliasSize field. Knowing the starting size allows you to store and retrieve data
- of your own at the end of the record (see “Customizing Alias Records” later in
- this chapter). An alias record is typically 200 to 300 bytes long.
-
- The private Alias Manager data includes all of the location, verificiation, and
- mounting information needed to resolve the alias record with the various search
- strategies described in this chapter.
-
- When you create an alias record, you have the option of recording a relative
- path, that is, the path to the target from another file or directory on the same
- volume. (Relative path doesn’t work across volumes.) The beginning point of a
- relative path is called the fromFile. To record a relative path, the Alias
- Manager saves the distances from the target and the fromFile to their common
- parent, that is, the lowest-level directory that appears in the pathnames of
- both. The Alias Manager can later use those distances in conjunction with the
- full pathname to conduct a relative search.
-
- Suppose, for example, that you are writing a word-processing application that
- allows the user to build a customized, supplemental dictionary for each
- document. You create the dictionary as a separate document in the same directory
- as the document it serves, as Figure 27-1 shows.
-
- ¿ Figure 27-1 Resolving a relative path ø
-
- When resolving the alias record by using a relative path, the Alias Manager
- starts at the directory that is the specified distance above the fromFile, the
- directory named Sample in the example in Figure 27-1. The Alias Manager then
- constructs a partial pathname by extracting one field of the absolute pathname
- for each step from the target to the common parent. In this example, the
- distance is one, so the pathname contains only the name of the target document,
- Dictionary.
-
- In some circumstances, a relative search identifies the correct target when a
- direct search cannot. For example, suppose the user of your word-processing
- application creates a working copy of a document and dictionary by copying the
- entire folder Sample to another disk. The user later updates the original
- document and dictionary by copying the folder from the working disk. All of the
- underlying file and directory identifications change, but the filenames and
- relative path remain the same. When the user later runs the spelling checker on
- the document, a relative-path search finds the correct target dictionary.
-
- The Alias Manager accepts and returns file specifications in the form of file
- system specification records (FSSpec records), described in the File Manager
- chapter of this volume. The FSSpec record represents a standard, complete
- description of a file system object. It contains a volume reference number, a
- parent directory ID, and a name.
-
- _______________________________________________________________________________
-
- æKY Search…Strategies3.…Volume…VI
- æC »Search Strategies3. Volume VI The Alias Manager
- _______________________________________________________________________________
-
- One of the key features of the Alias Manager is the search strategies built into
- the alias-resolution functions. The search strategies are designed to find the
- original target of an alias record, even if the target has been moved, renamed,
- copied, or restored from backup.
-
- The Alias Manager provides two basic alias-resolution algorithms: a fast search
- and an exhaustive search. This section describes the search algorithms. For
- descriptions of the functions that perform the searches, see “Resolving Alias
- Records” and “Resolving and Reading Alias Records” later in this chapter.
-
- The first step in any nonrelative search is to identify the volume on which the
- target resides. The volume search considers the volume’s name, creation date
- (which acts almost as a unique identifier for a volume), and type (for example,
- a hard disk, a 3.5-inch floppy disk, or an AppleShare volume).
-
- The Alias Manager first looks for a volume that matches all three criteria:
- name, creation date, and type. The search succeeds if the volume is mounted and
- if its name and creation date have not changed since the record was created. If
- the search fails, the Alias Manager attempts to match by creation date and type
- only. This step locates volumes that have been renamed. Finally, the Alias
- Manager attempts to match by volume name and type only.
-
- If the target is on an unmounted AppleShare volume, the Alias Manager attempts
- to mount the volume. It presents a name and password dialog if appropriate. If
- the target is on an unmounted ejectable volume, the Alias Manager displays a
- dialog box prompting the user to insert the volume. Your application can
- suppress the automatic mounting, as explained in the description of the
- MatchAlias function in “Alias Manager Routines.”
- _______________________________________________________________________________
-
- æKY Fast…Search
- æC »Fast Search The Alias Manager
- _______________________________________________________________________________
-
- The fast-search algorithm is designed to find the target of an alias record
- quickly.
-
- Depending on how you invoke it, the fast-search algorithm starts with either a
- relative search (described earlier in “About Alias Records”) or a direct search
- (described in this section). Fast search can perform a relative search whether
- or not it has identified the target volume, but it must identify the volume
- before it can perform a direct search.
-
- In a direct search, the fast-search algorithm first looks for the target by file
- ID (if the target is a file) or directory ID (if the target is a directory).
- (File IDs and directory IDs are described in the File Manager chapter of this
- volume.) Even if a file has been renamed or moved on a volume, the Alias Manager
- can find it quickly through its file ID.
-
- If the search by file ID or directory ID fails, fast search looks for the target
- by name in the original parent directory. This search locates the target if its
- file or directory ID has changed but it still exists by the same name in the
- parent directory (for example, if the target was restored from backup). Fast
- search compares file numbers on files found by name in the correct parent
- directory. If the file numbers do not match, the file is treated as a possible
- match, that is, it is put on the list of candidates and the search continues. If
- the target is not found by name in the parent directory, fast search looks for a
- file by file number in the parent directory. A file with the same file number
- but a different name replaces a file with the same name but a different file
- number in the list of matches.
-
- If the search by file ID or directory ID fails and if fast search cannot find
- the original parent directory, it searches for the target by full pathname. This
- search finds the target if it resides in the same location on the volume but the
- directory ID of its parent directory has changed (for example, if the entire
- parent directory was restored from backup).
-
- If the search by full pathname fails, fast search attempts to find the file by
- tracing partial pathnames up through all parent directories, using parent
- directory IDs instead of directory names. For example, consider this full
- pathname:
-
- Loma Prieta:MyReports:October:Sales Report
-
- If the search by full pathname fails, fast search first looks for the partial
- pathname :Sales Report in the directory with the ID that the directory Loma
- Prieta:MyReports:October had when the alias record was created. If that search
- fails, it looks for :October:Sales Report in the directory with the ID that Loma
- Prieta:MyReports had, and so on.
-
- If you did not ask for a search by relative path first but did provide a
- starting point for a relative search, and if the alias record contains relative
- path information, fast search performs a relative search after the direct
- search. The relative search succeeds if the relative path is the same as when
- the record was created and if the names of the target and its intervening parent
- directories have not changed.
-
- _______________________________________________________________________________
-
- æKY Exhaustive…Search
- æC »Exhaustive Search The Alias Manager
- _______________________________________________________________________________
-
- The exhaustive-search algorithm scans an entire volume to look for possible
- matches.
-
- The Alias Manager typically performs an exhaustive search by calling the File
- Manager function PBCatSearch, searching for files or directories with a matching
- creation date, creator, and type. (See the File Manager chapter of this volume
- for a description of PBCatSearch.)
-
- PBCatSearch is available only on HFS volumes, not on MFS volumes. (See the File
- Manager chapter of this volume for a description of the two file systems.)
- PBCatSearch is also available only on systems running version 7.0 and later.
- When PBCatSearch is not available, exhaustive search performs a search of the
- entire volume by making a series of indexed File Manager calls, searching for
- objects with matching creation date, type, creator, or file number.
-
- _______________________________________________________________________________
-
- æKY Using…the…Alias…Manager…Volume…VI
- æC »Using the Alias Manager Volume VI The Alias Manager
- _______________________________________________________________________________
-
- You use the Alias Manager primarily to create and resolve alias records. You can
- also use it to get information about and update alias records.
-
- The Alias Manager creates an alias record in memory and provides you with a
- handle to the record. When you no longer need a record in memory, free the
- memory by calling the DisposHandle procedure, described in the Memory Manager
- chapter of Volume II. You can store and retrieve alias records as resources of
- type 'alis'.
-
- Alias Manager functions accept and return file specifications in the form of
- FSSpec records, which contain a volume reference number, a parent directory ID,
- and a target name. See the File Manager chapter in this volume for a description
- of file identification conventions.
-
- Before calling any of the Alias Manager functions, verify that the Alias Manager
- is available by calling the Gestalt function with a selector of
- gestaltAliasMgrAttr. If Gestalt sets the gestaltAliasMgrPresent bit in the
- response, the Alias Manager is present. For a complete description of the
- Gestalt function, see the Compatibility Guidelines chapter of this volume.
-
- For more detailed descriptions of the functions described in this section, see
- “Alias Manager Routines” later in this chapter.
-
- _______________________________________________________________________________
-
- æKY Creating…Alias…Records
- æC »Creating Alias Records The Alias Manager
- _______________________________________________________________________________
-
- You create a new alias record by calling one of three functions: NewAlias,
- NewAliasMinimal, or NewAliasMinimalFromFullpath. The NewAlias function creates a
- complete alias record that can make full use of the alias-resolution algorithms.
- The other two functions are streamlined variations designed for circumstances
- when speed is more important than robust resolution services. All three
- functions allocate the memory for the record, fill it in, and provide a handle
- to it.
-
- NewAlias always records the name and the file or directory ID of the target, its
- creation date, the parent directory name and ID, and the volume name and
- creation date. It also records the full pathname of the target and a collection
- of other information. You can request that NewAlias store relative path
- information as well by supplying a starting point for a relative path (see
- “About Alias Records” earlier in this chapter for a description of relative
- path).
-
- Call NewAlias when you want to create an alias record to store for later use.
- For example, suppose you are writing a word-processing application that allows
- the user to customize a dictionary for use with a single text file. Your
- application stores the custom data in a separate dictionary file in the same
- directory as the document. As soon as you create the dictionary file, you call
- NewAlias to create an alias record for that file, including path information
- relative to the user’s text file:
-
- MyErr := NewAlias(textFile, target, myAliasHdl);
-
- The textFile parameter is a pointer to a file system specification record that
- identifies the starting point for the relative search, in this case the user’s
- text file. If you do not want relative path information recorded, pass a value
- of NIL in the first parameter.
-
- The target parameter is a file system specification record that identifies the
- target file, in this example the dictionary file.
-
- The myAliasHdl parameter is a variable in which the Alias Manager returns the
- handle to the alias record that describes the target.
-
- The two variations on the NewAlias function, NewAliasMinimal and
- NewAliasMinimalFromFullpath, record only a minimum of information about the
- target. NewAliasMinimal records only the target’s name, parent directory ID,
- volume name and creation date, and the volume mounting information.
- NewAliasMinimalFromFullpath records only the full pathname of the target,
- including the volume name.
-
- Use NewAliasMinimal or NewAliasMinimalFromFullpath when you are willing to give
- up robust alias-resolution service in return for speed. The Finder, for example,
- stores minimal aliases in the Apple events that tell your application to open or
- print a document. Because the alias record is resolved almost immediately, the
- description is likely to remain valid, and the shorter record is probably safe.
-
- You can use NewAliasMinimalFromFullpath to create an alias record for a target
- that doesn’t exist or that resides on an unmounted volume.
-
- _______________________________________________________________________________
-
- æKY Resolving…Alias…Records
- æC »Resolving Alias Records The Alias Manager
- _______________________________________________________________________________
-
- The Alias Manager provides two alias-resolution functions:
-
- • the high-level function ResolveAlias, which performs a fast search and
- identifies only one target
-
- • the low-level function MatchAlias, which can perform a fast search, an
- exhaustive search, or both, and which can return a list of target
- candidates
-
- In general, when you want to identify only the single most likely target of an
- alias record, you call ResolveAlias. You call MatchAlias when you want your
- program to control the search.
-
- This section describes the alias-resolution functions. The section “Search
- Strategies for Resolving Alias Records,” earlier in this chapter, describes the
- underlying fast and exhaustive searches.
-
- _______________________________________________________________________________
-
- æKY Resolvealias
- æC »Resolvealias The Alias Manager
- _______________________________________________________________________________
-
- Typically, you call the ResolveAlias function to resolve an alias record.
- ResolveAlias performs a fast search (described earlier in “Strategies for
- Resolving Alias Records”) and exits after it identifies one target.
-
- By calling low-level functions, ResolveAlias compares some key information about
- the identified target with the information stored in the alias record. If any of
- the information is different, ResolveAlias automatically updates the record.
-
- Note: As with all other Alias Manager functions, ResolveAlias updates the
- record only in memory. Your application is responsible for updating alias
- records
- stored on disk when appropriate.
-
- In the dictionary example, illustrated in Figure 27-1 earlier in the chapter,
- the application calls ResolveAlias when the user runs the spelling checker on a
- document with a customized dictionary.
-
- MyErr := ResolveAlias(textFile, myAliasHdl, target, wasChanged);
-
- The textFile parameter is a pointer to a file system specification record that
- identifies the starting point for the relative search, in this case the user’s
- text file. If you do not want relative path information used in the search, pass
- a value of NIL in the first parameter. If you provide a relative starting point,
- ResolveAlias performs the relative search first.
-
- The myAliasHdl parameter is a handle to the alias record to be resolved. In this
- example, the alias record describes the dictionary file.
-
- The target parameter is the file system specification record where the Alias
- Manager places the results of its search. After ResolveAlias completes, target
- contains the specification for the dictionary file.
-
- The ResolveAlias function uses the wasChanged parameter to report whether or not
- it updated the alias record. After ResolveAlias completes, wasChanged is TRUE if
- the record was updated and FALSE if it was not. If you are storing the alias
- record, check the value of wasChanged (as well as the function’s result code) to
- see whether to update the stored record after resolving an alias.
-
- If ResolveAlias can’t resolve the alias record, it returns a non-zero result
- code. A result code of fnfErr signals that ResolveAlias has found the correct
- volume and parent directory but not the target file or folder. In this case,
- ResolveAlias constructs a valid FSSpec record that describes the target. You can
- use this record to explore possible solutions to the resolution failure. You
- can, for example, use the FSSpec record to create a replacement for a missing
- file with the File Manager function FSpCreate.
-
- _______________________________________________________________________________
-
- æKY Matchalias
- æC »Matchalias The Alias Manager
- _______________________________________________________________________________
-
- The MatchAlias function is a low-level routine that gives your application
- control over the searching algorithm.
-
- You can control
-
- • whether to attempt an automatic mounting of unmounted volumes
-
- • whether to search on more than one volume
-
- • whether to perform a fast search, an exhaustive search, or both
-
- • the order of the direct and relative searches in a fast search
-
- • whether to pursue search strategies that require interaction with the user
- (such
- as asking for a password while mounting an AppleShare volume)
-
- You can also specify a maximum number of candidates that MatchAlias can
- identify.
-
- See “Alias Manager Routines” later in this chapter for details about controlling
- a search with the MatchAlias function.
-
- You can supply an optional filter function which MatchAlias calls
-
- • each time it identifies a possible match
-
- • when three seconds have elapsed without a match
-
- The filter function determines whether or not each candidate is added to the
- list of possible targets. It can also terminate the search. See “Filtering
- Possible Targets” later in this chapter for a description of the filter
- function.
-
- MatchAlias returns all candidates that it identifies in an array of file system
- specification records.
-
- _______________________________________________________________________________
-
- æKY Maintaining…Alias…Records
- æC »Maintaining Alias Records The Alias Manager
- _______________________________________________________________________________
-
- You can store alias records as resources of type 'alis'.
-
- CONST rAliasType = 'alis';
-
- To store and retrieve resources, use the standard Resource Manager functions
- (AddResource, GetResource, and GetNamedResource) described in the Resource
- Manager chapter of Volume I.
-
- To update an alias record, use the UpdateAlias function. You typically call
- UpdateAlias any time you know that the target of an alias record has been
- renamed or otherwise changed.
-
- You are most likely to call UpdateAlias after a call to the MatchAlias function.
- If MatchAlias identifies a single target, it sets a flag telling you whether or
- not the key information about the target file matches the information in the
- alias record. It is the responsibility of your application to update the record.
-
- The ResolveAlias function automatically updates an alias record if any of the
- the key information about the identified target does not match the information
- in the record.
-
- _______________________________________________________________________________
-
- æKY Getting…Information…About…Alias…Records
- æC »Getting Information About Alias Records The Alias Manager
- _______________________________________________________________________________
-
- To retrieve information from an alias record without actually resolving the
- record, call the GetAliasInfo function. You can use GetAliasInfo to retrieve the
- name of the target, the names of the target’s parent directories, the name of
- the target’s volume, or, in the case of an AppleShare volume, its zone or server
- name.
-
- _______________________________________________________________________________
-
- æKY Customizing…Alias…Records
- æC »Customizing Alias Records The Alias Manager
- _______________________________________________________________________________
-
- An alias record contains two kinds of information: public information available
- to your application and private information available only to the Alias Manager.
- Your application can use the first field, userType, to store its own signature
- or any other data that fits into 4 bytes. Your application can use the second
- field, aliasSize, to customize the alias record for storing additional data.
-
- The Alias Manager stores the size of the record when it is created or updated in
- the aliasSize field. To customize an alias record, you first increase the size
- of the record with the SetHandleSize procedure, described in the Memory Manager
- chapter of Volume II. You can then find the starting address of your own data in
- the record by adding the record’s starting address to the length recorded in the
- aliasSize field. If you expand the record through the Memory Manager, the Alias
- Manager preserves your data, even if it changes the size of its own data when
- updating the record.
-
- In general, you should customize only alias records that you have created.
-
- _______________________________________________________________________________
-
- æKY Alias…Manager…Routines…Volume…VI
- æC »Alias Manager Routines Volume VI The Alias Manager
- _______________________________________________________________________________
-
- This section describes the routines you use to create, update, resolve, and read
- alias records.
-
- Alias Manager routines use file system specification records (FSSpec records) to
- identify files, directories, and volumes. To create a FSSpec record, call the
- function MakeFSSpec, described in the File Manager chapter of this volume.
-
- The Alias Manager routines can return the result codes listed in this section or
- any other applicable file-system or memory-management result codes.
-
-
-
-
-
-
-
- _______________________________________________________________________________
-
- æKY Creating…and…Updating…Alias…Records
- æC »Creating and Updating Alias Records The Alias Manager
- _______________________________________________________________________________
-
- You use the NewAlias function to create a complete alias record.
-
- FUNCTION NewAlias (fromFile: FSSpecPtr; target: FSSpec;
- VAR alias: AliasHandle) : OSErr;
-
- NewAlias creates an alias record that describes the specified target. It
- allocates the storage, fills in the record, and puts a record handle in the
- alias parameter. NewAlias always records the name and file or directory ID of
- the target, its creation date, the parent directory name and ID, and the volume
- name and creation date. It also records the full pathname of the target and a
- collection of other information relevant to locating the target, verifying the
- target, and mounting the target’s volume, if necessary. You can request that it
- store relative path information as well by supplying a starting point for a
- relative path (see “About Alias Records” for a description of relative path).
-
- The fromFile parameter represents the starting point for a relative path, to be
- used later in a relative search. If you do not need relative path information in
- the record, pass a fromFile value of NIL. If you want NewAlias to record
- relative path information, pass a pointer to a valid FSSpec record in this
- parameter. The two files or directories, fromFile and target, must reside on the
- same volume.
-
- The target parameter is a FSSpec record for the target of the alias record.
-
- NewAlias puts a handle to the newly created alias record in the alias parameter.
- If the function fails to create an alias record, it sets alias to NIL.
-
- You use the NewAliasMinimal function to create a short alias record quickly.
-
- FUNCTION NewAliasMinimal (target: FSSpec; VAR alias: AliasHandle) :
- OSErr;
-
- NewAliasMinimal creates an alias record that contains only the minimum
- information necessary to describe the target: the target name, the parent
- directory ID, the volume name and creation date, and the volume mounting
- information. NewAliasMinimal uses the standard alias record data structure, but
- fills in only parts of the record.
-
- The target parameter points to a FSSpec record for the target of the alias
- record.
-
- NewAliasMinimal puts a handle to the newly created alias record in the alias
- parameter. If the function fails to create an alias record, it sets alias to
- NIL.
-
- The ResolveAlias function, described in “Resolving and Reading Alias Records”
- later in this chapter, never updates a minimal alias record.
-
- You use the function NewAliasMinimalFromFullpath to quickly create an alias
- record that contains only the full pathname of the target.
-
- FUNCTION NewAliasMinimalFromFullpath (fullpathLength: Integer;
- fullpath: Ptr; zoneName: Str32;
- serverName: Str31;
- VAR alias: AliasHandle) : OSErr;
-
- NewAliasMinimalFromFullpath creates an alias record that identifies the target
- by full pathname. You can call NewAliasMinimalFromFullpath to create an alias
- record for a file that doesn’t exist or that resides on an unmounted volume.
- NewAliasMinimalFromFullpath uses the standard alias record data structure, but
- it fills in only the information provided in the input parameters. You can
- therefore use NewAliasMinimalFromFullpath to create alias records for targets on
- unmounted volumes.
-
- The fullpathLength parameter identifies the number of characters in the full
- pathname.
-
- The fullpath parameter is a pointer to a buffer that contains the full pathname
- of the target. The full pathname starts with the name of the volume, includes
- all of the directory names in the path to the target, and ends with the target
- name. (For a description of pathnames, see the File Manager chapter in this
- volume.)
- The parameters zoneName and serverName are strings that identify the AppleTalk
- zone and server name of the AppleShare volume on which the target resides. Set
- these parameters to null strings if you do not need them.
-
- NewAliasMinimalFromFullpath puts a handle to the newly created alias record in
- the alias parameter. If the function fails to create an alias record, it sets
- alias to NIL.
-
- You use the UpdateAlias function to update an alias record.
-
- FUNCTION UpdateAlias (fromFile: FSSpecPtr; target: FSSpec;
- alias: AliasHandle; VAR wasChanged: Boolean) :
- OSErr;
-
- UpdateAlias updates the alias record pointed to by the alias parameter so that
- it describes the target specified by the target parameter. UpdateAlias rebuilds
- the entire alias record, filling it in as the NewAlias function would.
-
- The fromFile parameter represents the starting point for a relative path, to be
- used later in a relative search. If you do not need relative path information in
- the record, pass a fromFile value of NIL. If you want UpdateAlias to record
- relative path information, pass a pointer to a valid FSSpec record in this
- parameter. The two files or directories, fromFile and target, must reside on the
- same volume.
-
- The target parameter is the target of the alias record. This parameter must be a
- valid FSSpec record.
-
- The alias parameter is a handle to the alias record to be updated.
-
- If the newly constructed alias record is exactly the same as the old one,
- UpdateAlias sets the wasChanged parameter to FALSE. Otherwise, it sets it to
- TRUE. Check this parameter to determine whether you need to save an updated
- record.
-
- UpdateAlias always creates a complete alias record. When you update a minimal
- alias record with UpdateAlias, you convert the minimal record to a complete
- record.
-
- Result codes
- paramErr –50 target, alias, or both are NIL, or the alias
- record is corrupt
- _______________________________________________________________________________
-
- æKY Resolving…and…Reading…Alias…Records
- æC »Resolving and Reading Alias Records The Alias Manager
- _______________________________________________________________________________
-
- You use the ResolveAlias function to identify the single most likely target of
- an alias record.
-
- FUNCTION ResolveAlias (fromFile: FSSpecPtr; alias: AliasHandle;
- VAR target: FSSpec; VAR wasChanged: Boolean) :
- OSErr;
-
- ResolveAlias performs a fast search for the target of the alias, as described
- earlier in “Search Strategies for Resolving Alias Records.” If the resolution is
- successful, ResolveAlias returns the FSSpec record for the target file system
- object through the target parameter, updates the alias record if necessary, and
- reports whether or not the record was updated through the wasChanged parameter.
- If the target is on an unmounted AppleShare volume, ResolveAlias automatically
- mounts the volume. If the target is on an unmounted ejectable volume,
- ResolveAlias asks the user to insert the volume. ResolveAlias exits after it
- finds one acceptable target.
-
- The fromFile parameter represents the starting point for a relative search. If
- you pass a fromFile parameter of NIL, ResolveAlias performs only a direct
- search. If you pass a pointer to a valid FSSpec record in the fromFile
- parameter, ResolveAlias performs a relative search for the target, followed by a
- direct search only if the relative search fails. If you want to perform a direct
- search followed by a relative search, you must use the MatchAlias function.
-
- The alias parameter is a handle to the alias record to be resolved and, if
- necessary, updated.
-
- The target parameter receives the FSSpec record of the target file system
- object.
-
- After it identifies a target, ResolveAlias compares some key information about
- the target with the information in the alias record. (The upcoming description
- of the MatchAlias function lists the key information.) If the information is
- different, ResolveAlias updates the record to match the target. If it updates
- the alias record, ResolveAlias sets the wasChanged parameter to TRUE. Otherwise,
- it sets it to FALSE. (Because ResolveAlias never updates a minimal alias, it
- never sets wasChanged to TRUE when resolving a minimal alias.)
-
- When it finds the specified volume and parent directory but fails to find the
- target file or directory in that location, ResolveAlias returns a result code of
- fnfErr and fills in the target parameter with a complete FSSpec record
- describing the target (that is, the volume reference number, parent directory
- ID, and file or folder name). The FSSpec record is valid, although the object it
- describes does not exist. This information is intended as a “hint” that lets you
- explore possible solutions to the resolution failure. You can, for example, use
- the FSSpec record to create a replacement for a missing file with the File
- Manager function FSpCreate.
-
- ResolveAlias displays the standard dialog boxes when it needs input from the
- user, such as a name and password for mounting a remote volume. The user can
- cancel the resolution through these dialog boxes.
-
- Result codes
- dirNFErr –120 Parent directory not found
- fnfErr –43 Target not found, but
- volume and parent
- directory found;
- target parameter
- contains a
- valid FSSpec
- record
- nsvErr –35 Volume not found
- paramErr –50 The alias parameter is NIL, or
- the alias record is
- corrupt
- usrCanceledErr –128 The user cancelled
-
- You use the MatchAlias function to identify a list of possible matches and pass
- the list through an optional selection filter. The filter can pass more than one
- possible match.
-
- FUNCTION MatchAlias (fromFile: FSSpecPtr; rulesMask: LongInt;
- alias: AliasHandle; VAR aliasCount: Integer;
- aliasList: FSSpecArrayPtr; VAR needsUpdate: Boolean;
- aliasFilterProcPtr: ProcPtr; yourDataPtr: UNIV Ptr)
- : OSErr;
-
- MatchAlias resolves the alias record specified by the alias parameter, following
- the rules specified by the rulesMask parameter, and returns a list of possible
- candidates in the structure specified by the aliasList parameter. MatchAlias
- places the number of candidates identified in the aliasCount parameter.
-
- The fromFile parameter represents the starting point for a relative search. If
- you do not want MatchAlias to perform a relative search, set fromFile to NIL. If
- you want MatchAlias to perform a relative search, pass a pointer to a file
- system specification record that describes the starting point for the search.
-
- The rulesMask parameter specifies a set of rules to guide the resolution. Pass
- the sum of all of the rules you want to invoke.
-
- Constant Description
-
- kARMsearch Perform a fast search for the alias target.
-
- If kARMsearchRelFirst is not set,
- perform a direct search
- first, followed by a relative
- search only if the fromFile
- parameter is not NIL and the list
- of matches is not full.
-
- kARMsearchMore Perform an exhaustive search for the alias target.
-
- On HFS volumes, the exhaustive
- search uses the File
- Manager function PBCatSearch to
- identify candidates with
- matching creation date, type, and
- creator. PBCatSearch is
- available only on HFS volumes and
- only on systems
- running version 7.0 or later. On
- MFS volumes or HFS
- volumes that do not support
- PBCatSearch the exhaustive
- search makes a series of indexed
- calls to File Manager
- functions, using the same search
- criteria.
-
- If you set kARMsearchMore and one
- or both of
- kARMsearch and
- kARMsearchRelFirst, MatchAlias
- performs the fast search first.
-
- kARMsearchRelFirst If kARMsearch is also set, perform a relative search
- before
- the direct search. (If kARMsearch
- is also set and the target
- is found through the direct
- search, MatchAlias sets the
- needsUpdate flag to TRUE.)
-
- If neither kARMsearch nor
- kARMsearchMore is set,
- perform only a relative search.
-
- If kARMsearch is not set but
- kARMsearchMore is set,
- perform a relative search
- followed by an exhaustive
- search.
-
- kARMmountVol Automatically try to mount the target’s volume if it
- is not
- mounted.
-
- kARMmultVols Search all mounted volumes.
-
- The search begins with the volume
- on which the target
- resided when the record was
- created.
-
- When you specify a fast search of
- all mounted volumes,
- MatchAlias performs a formal fast
- search only on the
- volume described in the alias
- record. On all other
- volumes, it looks for the target
- by ID or by name in the
- directory with the specified
- parent directory ID.
-
- When you specify an exhaustive
- search of multiple
- volumes, MatchAlias performs the
- same search on all
- volumes.
-
- When resolving an alias record
- created by
- NewAliasMinimalFromFullpath,
- MatchAlias ignores this
- flag.
-
- kARMnoUI Stop if a search requires user interaction, such
- as a
- password dialog box when mounting a
- remote volume.
-
- If user interaction is needed and
- kARMnoUI is in effect,
- the search fails.
-
- You must specify at least one of the first three parameters: kARMsearch,
- kARMsearchMore, and kARMsearchRelFirst.
-
- The alias parameter is a handle to the alias record to be resolved.
-
- Your application can specify a maximum number of possible matches by setting the
- aliasCount parameter. MatchAlias changes the aliasCount parameter to the actual
- number of candidates identified. If MatchAlias finds the parent directory on the
- correct volume but does not find the target, it sets the aliasCount parameter to
- 1, puts the file system specification record for the target in the results list,
- and returns fnfErr. The FSSpec record is valid, although the object it describes
- does not exist. This information is intended as a “hint” that lets you explore
- possible solutions to the resolution failure. You can, for example, use the
- FSSpec record to create a replacement for a missing file with the File Manager
- function FSpCreate.
-
- The aliasList parameter points to the array that holds the results of the
- search.
-
- The needsUpdate flag is a signal to your application that the record might need
- to be updated. After it identifies a target, MatchAlias compares some key
- information about the target with the same information in the record. If the
- information does not match, MatchAlias sets the needsUpdate flag to TRUE. The
- key information is
-
- • the name of the target
-
- • the directory ID of the target’s parent
-
- • the file ID or directory ID of the target
-
- • the name and creation date of the volume on which the target resides
-
- MatchAlias also sets the needsUpdate flag to TRUE if it identifies a list of
- possible matches rather than a single match or if kARMsearchRelFirst is set but
- the target is identified through either a direct search or an exhaustive search.
- Otherwise, MatchAlias sets the needsUpdate flag to FALSE. MatchAlias always sets
- the needsUpdate flag to FALSE when resolving an alias created by
- NewAliasMinimal. If you want to update the alias record to reflect the final
- results of the resolution, call UpdateAlias.
-
- The aliasFilter parameter points to a filter function supplied by your
- application. The Alias Manager executes this function each time it identifies a
- possible match and after the search has continued for three seconds without a
- match. Your filter function returns a Boolean value that determines whether the
- possible match is discarded (TRUE) or added to the list of possible targets
- (FALSE). It can also terminate the search by setting the variable parameter
- quitFlag. See “Filtering Possible Targets” later in the chapter for a
- description of the filter function, which follows this syntax:
-
- FUNCTION MyMatchAliasFilter (cpbPtr: CInfoPBPtr;
- VAR quitFlag: Boolean;
- myDataPtr: Ptr): Boolean;
-
- The yourDataPtr parameter can point to any data that your application might need
- in the filter function. Use the myDataPtr parameter to pass global or local data
- to your filter function.
-
- Result codes
- nsvErr –35 The volume is not mounted
- fnfErr –43 No target was found
- paramErr –50 target, alias, or both are NIL, or
- the alias record is
- corrupt
- usrCanceledErr –128 The user cancelled the operation
-
- You can use the GetAliasInfo function to get information from an alias record
- without actually resolving the record.
-
- FUNCTION GetAliasInfo (alias: AliasHandle; index: AliasInfoType;
- VAR theString: Str63 ) : OSErr;
-
- GetAliasInfo retrieves the information specified by the index parameter from the
- record pointed to by the alias parameter and places it in the parameter
- theString.
-
- The alias parameter is a handle to the alias record to be read.
-
- The index parameter specifies the kind of information to be retrieved. If index
- is a positive integer, GetAliasInfo retrieves the parent directory that has the
- same hierarchical level above the target as the index parameter (for example, an
- index value of 2 returns the name of the parent directory of the target’s parent
- directory). You can therefore assemble the names of the target and all of its
- parent directories by making repeated calls to GetAliasInfo with incrementing
- index values, starting with a value of 0. When index is greater than the number
- of levels between the target and the root, GetAliasInfo returns an empty string.
- You can also set the index parameter to one of these values:
-
- Constant Value Description
-
- asiZoneName –3 If the record represents a target on an
- AppleShare
- volume, retrieve the
- server’s zone name.
- Otherwise,
- return an empty string.
-
- asiServerName –2 If the record represents a target on an
- AppleShare
- volume, retrieve the
- server name. Otherwise,
- return
- an empty string.
-
- asiVolumeName –1 Return the name of the volume on which the
- target
- resides.
-
- asiAliasName 0 Return the name of the target.
-
- asiParentName 1 Return the name of the parent directory
- of the target
- of the record. If the
- target is a volume,
- return the
- volume name.
-
- GetAliasInfo places the requested information in the parameter theString.
-
- GetAliasInfo returns the information stored in the alias record, which might not
- be current. To ensure that the information is current, you can resolve and
- update the alias record before calling GetAliasInfo.
-
- GetAliasInfo cannot provide all kinds of information on a minimal alias.
-
- Result codes
- paramErr –50 alias, theString, or both are NIL;
- the index is less
- than asiZoneName; or
- the alias record is
- corrupt
- _______________________________________________________________________________
-
- æKY Filtering…Possible…Targets
- æC »Filtering Possible Targets The Alias Manager
- _______________________________________________________________________________
-
- You can write your own filter function to examine possible targets identified by
- the MatchAlias function. MatchAlias calls your filter function each time it
- identifies a possible match and when three seconds have elapsed without a match.
-
- The filter function takes three parameters and returns a Boolean value:
-
- FUNCTION MyMatchAliasFilter (cpbPtr: CInfoPBPtr; VAR quitFlag: Boolean;
- myDataPtr: Ptr): Boolean;
-
- The cpbPtr parameter points to the catalog information parameter block record
- (as returned by the File Manager function PBGetCatInfo) of the possible match.
- MatchAlias sets this parameter to NIL if it is calling your function to give it
- the periodic chance to terminate the search. (Do not use this pointer without
- checking for NIL.)
-
- Your filter function sets the quitFlag parameter to terminate the search.
-
- The myDataPtr parameter points to any customized data that your application
- passed when it called MatchAlias. This parameter allows your filter function to
- access any data that your application has set up on its own.
-
- The Boolean return value determines whether the possible match is discarded
- (TRUE) or added to the list of possible targets (FALSE).
-
- _______________________________________________________________________________
-
- æKY Summary…of…the…Alias…Manager…Volume…VI
- æC »Summary of the Alias Manager Volume VI The Alias Manager
- _______________________________________________________________________________
-
- Click the arrow in the lower-right corner of this wondow to see the summary
- sections of the constants, data types, and routines for the Alias Manager.
- _______________________________________________________________________________
-
- æKY Alias…Manager…Constants
- æC »Alias Manager Constants The Alias Manager
- _______________________________________________________________________________
-
- CONST
- rAliasType = 'alis'; {alias record resource type}
-
- {rulesMask for MatchAlias}
- kARMmountVol = $0001; {mount the volume automatically}
- kARMnoUI = $0002; {suppress user interface}
- kARMmultVols = $0008; {search on multiple volumes}
- kARMsearch = $0100; {perform a fast search}
- kARMsearchMore = $0200; {perform an exhaustive search}
- kARMsearchRelFirst = $0400; {perform a relative search first}
-
- {index values for GetAliasInfo}
- asiZoneName = –3; {get zone name}
- asiServerName = –2; {get server name}
- asiVolumeName = –1; {get volume name}
- asiAliasName = 0; {get target name}
- asiParentName = 1; {get parent directory name}
- _______________________________________________________________________________
-
- æKY Alias…Manager…Data…Types
- æC »Alias Manager Data Types The Alias Manager
- _______________________________________________________________________________
-
- TYPE AliasHandle = ^AliasPtr;
- AliasPtr = ^AliasRecord;
-
- AliasRecord =
- RECORD
- userType: OSType; {application’s signature}
- aliasSize: Integer; {size of record when created}
- {variable-length private data}
- END;
-
- AliasInfoType = Integer; {alias record information type}
-
- AliasFilterProcPtr = ProcPtr; {application-defined routine; }
- { see sample }
- { FUNCTION MyMatchAliasFilter}
- _______________________________________________________________________________
-
- æKY Alias…Manager…Routines…Summary
- æC »Alias Manager Routines Summary The Alias Manager
- _______________________________________________________________________________
-
- Creating and Updating Alias Records
-
- FUNCTION NewAlias (fromFile: FSSpecPtr;
- target: FSSpec;
- VAR alias: AliasHandle) : OSErr;
- FUNCTION NewAliasMinimal (target: FSSpec;
- VAR alias: AliasHandle) : OSErr;
- FUNCTION NewAliasMinimalFromFullpath (fullpathLength: Integer;
- fullpath: Ptr; zoneName: Str32;
- serverName: Str31;
- VAR alias: AliasHandle) : OSErr;
- FUNCTION UpdateAlias (fromFile: FSSpecPtr;
- target: FSSpec; alias: AliasHandle;
- VAR wasChanged: Boolean) : OSErr;
-
-
- Resolving and Reading Alias Records
-
- FUNCTION ResolveAlias (fromFile: FSSpecPtr;
- alias: AliasHandle;
- VAR target: FSSpec;
- VAR wasChanged: Boolean) : OSErr;
-
- FUNCTION MatchAlias (fromFile: FSSpecPtr;
- rulesMask: LongInt;
- alias: AliasHandle;
- VAR aliasCount: Integer;
- aliasList: FSSpecArrayPtr;
- VAR needsUpdate: Boolean;
- aliasFilterProcPtr: ProcPtr;
- yourDataPtr: UNIV Ptr) : OSErr;
-
- FUNCTION GetAliasInfo (alias: AliasHandle;
- index: AliasInfoType;
- VAR theString: Str63) : OSErr;
- _______________________________________________________________________________
-
- æKY Alias…Manager…Application-Defined…Routine
- æC »Alias Manager Application-Defined Routine The Alias Manager
- _______________________________________________________________________________
-
- FUNCTION MyMatchAliasFilter (cpbPtr: CInfoPBPtr;
- VAR quitFlag: Boolean;
- myDataPtr: Ptr): Boolean;
- _______________________________________________________________________________
-
- æKY Alias…Manager…Result…Codes
- æC »Alias Manager Result Codes The Alias Manager
- _______________________________________________________________________________
-
- nsvErr –35 The volume is not mounted
- fnfErr –43 No target was found
- paramErr –50 One or more parameters are NIL, or a handle
- is corrupt
- dirNFErr –120 Parent directory not found
- usrCanceledErr –128 The user cancelled the operation
- _______________________________________________________________________________
-
- æKY Alias…Manager…Assembly-Language…Information
- æC »Alias Manager Assembly-Language Information The Alias Manager
- _______________________________________________________________________________
-
- Alias Record Data Structure
-
- userType 4 bytes file type of target file
- aliasSize 2 bytes size of record in bytes
- {variable-length private data}
-
-
-
-
- _______________________________________________________________________________
-
-
- æKY AppleDesktopBus
- æC
- THE APPLE DESKTOP BUS
- _______________________________________________________________________________
-
- About…The…AppleDesktopBus…Chapter
- About…the…Apple…Desktop…Bus
- ADB…Manager…Routines
- Writing…ADB…Device…Drivers
- Summary…of…the…ADB
- _______________________________________________________________________________
-
-
-
- æKY About…The…AppleDesktopBus…Chapter
- æC »ABOUT THIS CHAPTER AppleDesktopBus
- _______________________________________________________________________________
-
- This chapter tells you how to accomplish low-level communication with peripheral
- devices that are connected to the Apple Desktop Bus (ADB).
-
- Reader’s guide: The standard mouse and keyboard drivers automatically take
- care of all required ADB access functions. When the user
- manipulates the mouse or keyboard, the system calls the
- appropriate driver and the application never uses the ADB
- Manager. Hence you need the information in this chapter only
- if you are writing a special driver, such as a driver for a
- new user-input device.
-
- The ADB is a simple local-area network that connects low-speed input-only devices to
- the operating system. In the Macintosh II and Macintosh SE computers, the ADB is used
- to communicate with one or more keyboards, the mouse, and other user input devices.
-
- Keys located on multiple keyboards are distinguished by the keyboard event message,
- as described in the Toolbox Event Manager chapter.
-
- Note: An ADB, using the same operating protocols, is also part of the
- Apple IIgs computer.
-
- This chapter contains three principal sections:
-
- • a description of the Apple Desktop Bus and how it works
- • a description of the ADB Manager. This section of system ROM contains
- the routines that a driver must use to access devices connected to the ADB.
- • a discussion of the special requirements for drivers that support
- devices connected to the ADB
-
- You should already be familiar with
-
- • the hardware interface to the Apple Desktop Bus, described in the
- Macintosh Family Hardware Reference
- • events generated by ADB keyboard devices (described in the Toolbox
- Event Manager chapter) if your driver communicates with one or more
- keyboards
-
- _______________________________________________________________________________
-
-
- æKY About…the…Apple…Desktop…Bus
- æC »ABOUT THE APPLE DESKTOP BUS AppleDesktopBus
- _______________________________________________________________________________
-
- The Apple Desktop Bus connects up to 16 low-speed input-only devices to the Macintosh
- II or Macintosh SE computer. Each device can maintain up to four variable-size registers,
- whose contents can be read from or written to by the ADB network. Each register may
- contain from two to eight bytes. Two of the device registers have an assigned meaning
- and a standardized format: register 0, used for interrupt information, and register
- 3, containing the device’s identification number. The other two device registers have
- no assigned meaning, and may have different meanings for read and write operations.
-
- The system communicates with the Apple Desktop Bus through the system’s Versatile
- Interface Adapter chip (VIA). The VIA is described in the Macintosh Hardware chapter.
-
- Warning: The ADB does not support connecting a device while the computer
- is running. The result may be to reinitialize all devices on the
- bus without informing the system.
-
- The system always controls the bus. It issues commands to specific devices on the bus
- and they respond by accepting data, sending data, or changing their configuration.
- These commands are discussed below.
-
- Note: Devices connected to the ADB contain their own single-chip
- microprocessors, which handle both device routines and the
- ADB interface. If the system sends commands to a device with
- a duty cycle of more than 50%, the device’s microprocessor
- may become overloaded.
-
- _______________________________________________________________________________
-
- »Bus Commands
-
- Each bus command consists of a byte that the system sends to a device connected to
- the ADB. Applications may place bus commands on the network by calling the routine
- ADBOp, discussed under “ADB Manager Routines” later in this chapter. There are four
- bus commands; their bit layouts are shown in Figure 1. All other bit layouts are
- reserved.
-
- •••Refer to Figure 1.•••
-
- Figure 1–ADB Command Formats
-
- The individual commands are discussed below.
-
- Warning: Values of the low bytes of the ADB command formats other than
- those shown in Figure 1 are reserved, and should not be used.
-
- »SendReset
-
- The SendReset command forces a hardware reset of all devices connected to the ADB.
- Such a reset clears all pending device actions and places the devices in their startup
- state. All devices are able to accept new ADB commands and user inputs immediately
- thereafter. All devices ignore the high-order four bits of the SendReset command.
-
- »Flush
-
- The Flush command flushes data from the single device specified by the network address
- in its high-order four bits. Network addresses are discussed below, under “Device
- Addressing”. It purges any pending user inputs and make the device ready to accept
- new commands and input data.
-
- »Listen
-
- The Listen command is used to send instructions to devices connected to the ADB. It
- transfers data from a buffer in system RAM to a register in the device specified by
- the network address in its high-order four bits. The device register is specified by
- the low-order two bits of the Listen command.
-
- »Talk
-
- The Talk command is used to fetch user inputs from devices connected to the ADB. It
- is the complement of the Listen command. It transfers data from a register in the
- device specified by the network address in its high-order four bits to a buffer in
- system RAM. The device register is specified by the low-order two bits of the Talk
- command.
-
- _______________________________________________________________________________
-
- »Device Registers
-
- Each device connected to the ADB contains four registers, each of which may store
- from two to eight bytes of data. Each register is identified by the value of the
- low-order two bits in a Listen or Talk command. Registers 0 and 3 have dedicated
- functions; registers 1 and 2 are used for purposes specific to each device, and need
- not be present in a device.
-
- Note: ADB device registers are virtual registers; they need not be
- implemented physically. The device firmware must only respond
- to register commands as if a register were present.
-
- »Register 0
-
- Device register 0 is reserved for input data. If the device has user-input data to be
- fetched, it places the data in register 0 and requests service. It continues to
- request service until the system retrieves its data. The system responds to data-input
- requests with the following polling sequence:
-
- • It generates a Talk command for register 0 in each device connected
- to the ADB.
- • If the device has data to send, it responds. The system does not
- poll the next device until the data is exhausted.
- • If the device has no data to send, or if its data is exhausted, the
- VIA generates an interrupt. The system then polls the next device.
- • This process continues until no devices request service.
-
- »Register 3
-
- Device register 3 is reserved for device identification data and operating flags.
- Application programs may set this data with Listen commands and read it with Talk
- commands. Register 3 stores 16 bits, divided into the fields shown in Figure 2.
-
- •••Refer to Figure 2.•••
-
- Figure 2–Format of Device Register 3
-
- Except for commands that contain certain reserved device handler ID values
- (listed below), every command to register 3 changes the entire register contents.
- Hence to change part of the register, you should first fetch its current contents
- with a Talk command and then send it an updated value with Listen. You can change
- part of the contents of register 3 by using special device handler ID values, as
- described below.
-
- The device handler ID field indicates the device’s type. With certain devices, an
- application can change the device’s mode of operation by sending it a new ID value.
- If the device supports the new mode, it stores the new value in this field.
-
- Warning: You are assigned handler IDs by Apple Software Licensing, so
- they do not conflict with the values of other devices that may
- be connected to the ADB at the same time.
-
- When certain reserved values are sent to the device handler ID field by a Listen
- command, they are not stored in the field; instead, they cause specific device actions.
- Hence these values cannot be used as device ID values. They are the following:
-
- Value Action
-
- $00 Change bits 8–13 of register 3 to match the rest of the command;
- leave Device Handler ID value unchanged.
- $FD Change Device Address to match bits 8–11 if the device activator
- has been depressed; leave Device Handler ID value and flags unchanged.
- $FE Change Device Address to match bits 8–11 if the result produces no
- address duplication on the bus; leave Device Handler ID value and
- flags unchanged.
- $FF Initiate device self-test. If self-test succeeds, leave register 3
- unchanged; if self-test fails, clear Device Handler ID field to $00.
-
- Other Device Handler ID values may be stored in the field.
-
- Note: Device Handler ID values below $20 are reserved by Apple.
-
- The Device Address field indicates the device’s location within the 16 possible
- device locations of the ADB. An application may change its value with a Listen command.
- When this field is interrogated with a Talk command, it returns a random value. This
- helps you separate multiple devices that have the same ADB address; for further
- information, see “Device Addressing”, below.
-
- The Service Request Enable bit is set by the device to request an interrupt poll.
-
- _______________________________________________________________________________
-
- »Device Addressing
-
- There are 16 possible direct addresses, $00–$0F, for devices connected to the ADB.
- However, it is possible to connect more than one device to an address; this might
- happen, for example, in a system with two alternate keyboards.
-
- When several devices share a single ADB address, but there are free addresses available
- in the net, the system will automatically reassign addresses until they are all
- different. It will do this every time the ADB Manager is initialized or reinitialized.
- To find out a device’s new address, use the calls GetIndADB or GetADBInfo, described
- later in this chapter.
-
- _______________________________________________________________________________
-
- »Standard ADB Device Drivers
-
- The Macintosh II and Macintosh SE systems contain two standard ADB drivers:
-
- • the mouse driver, which supports the ADB mouse. The Apple mouse
- has an original ADB address of 3.
- • the universal keyboard driver, which supports all Apple ADB keyboards.
- The Apple keyboard has an original ADB address of 2, with a Device
- Handler ID of 1 for the Macintosh II keyboard and 2 for the Apple
- Extended Keyboard. These keyboards are described in the Toolbox
- Event Manager chapter.
-
- These drivers reside in the system ROM. In addition, ADB address 0 is reserved for
- the ADB chip itself. You can change the ADB addresses of the mouse or keyboard, as
- described above under “Device Registers,” but Apple does not recommend doing so.
-
- Assembly-language note: The ADB address of the keyboard on which the
- last-typed character was entered is now stored
- in the global variable KbdLast. The type of the
- keyboard on which the last-typed character was
- entered is stored in the global variable KbdType.
- The value of KbdType is the Device Handler ID
- value in Register 3 of the device; values below
- $20 are reserved by Apple.
-
- The requirements for writing new ADB device drivers are discussed later in this
- chapter.
-
- _______________________________________________________________________________
-
-
- æKY ADB…Manager…Routines
- æC »ADB MANAGER ROUTINES AppleDesktopBus
- _______________________________________________________________________________
-
- The ADB Manager consists of six routines located in the 256K ROM. You would use them
- only if you needed to access bus devices directly or communicate with a special
- device.
-
- Some of these routines access and update information in the ADB device table, a
- structure placed in the system heap by ROM code during system startup. It lists for
- each device the device’s type, its original ADB address, its current ADB address, the
- address of the routine that services the device, and the address of the area in RAM
- used for temporary data storage by its driver. The ADB device table is accessible
- only through ADB Manager routines.
-
- PROCEDURE ADBReInit;
-
- Trap macro _ADBReInit
-
- ADBReInit reinitializes the entire Apple Desktop Bus. It clears the ADB device table
- to zeros and places a SendReset command on the bus to reset all devices to their
- original addresses. ADBReInit has no parameters.
-
- Because it does not deallocate ADB resources on the system heap, ADBReInit should not
- be used for routine bus initialization. Apple strongly recommends against adding
- devices while the system is running; therefore, you should never call ADBReInit.
-
- ADBReInit also calls a routine pointed to by the low memory global JADBProc
- at the beginning and end of its execution. You can insert your own
- preprocessing/postprocessing routine by changing the value of JADBProc; ADBReInit
- conditions it by setting D0 to 0 for preprocessing and to 1 for postprocessing. Your
- procedure must restore the value of D0 and branch to the original value of JADBProc
- on exit. JADBProc should be used to de-allocate memory used by the driver (see
- MacDTS Sample Code “TbltDrvr” for an example), and then it should chain to the procedure
- originally found in JADBProc.
-
- The complete ADBReInit sequence is therefore the following:
-
- • JSR to JADBProc with D0 set to 0
- • reinitialize the Apple Desktop Bus
- • clear the ADB device table
- • JSR to JADBProc with D0 set to 1
-
- FUNCTION ADBOp (data: Ptr; compRout: ProcPtr; buffer: Ptr;
- commandNum: INTEGER) : OSErr;
-
- Trap macro _ADBOp
-
- On entry: A0: pointer to parameter block
- D0: commandNum (byte)
-
- Parameter block
- --> 0 buffer pointer
- --> 4 compRout pointer
- --> 8 data pointer
-
- On exit: D0: result code (byte)
-
- The completion routine pointed to by compRout will be passed the following parameters
- on entry:
-
- D0: commandNum (byte)
- A0: pointer to buffer, data stored as a Pascal string (maximum
- 8 bytes data preceded by one length byte)
- A1: pointer to completion routine (compRout)
- A2: pointer to optional data area (data)
-
- ADBOp transmits over the bus the command byte whose value is given by commandNum. The
- structure of the command byte is given earlier in Figure 1. ADBOp executes only when
- the ADB is otherwise idle; otherwise it is held in a command queue. It returns an
- error if the command queue is full. The length of the data buffer pointed to by
- buffer is contained in its first byte, like a Pascal string. The optional data area
- pointed to by data is for local storage by the completion routine pointed to by
- compRout. ADBop should be used sparingly; it is not intended for polling a device.
- The host automatically polls devices with data to deliver.
-
- Result codes noErr No error
- –1 Unsuccessful completion
-
- FUNCTION CountADBs: INTEGER;
-
- Trap macro _CountADBs
-
- On exit: D0: number of devices (byte)
-
- CountADBs returns a value representing the number of devices connected to the ADB by
- counting the number of entries in the device table. It has no arguments and returns
- no error codes.
-
- FUNCTION GetIndADB (VAR info: ADBDataBlock;
- devTableIndex: INTEGER) : ADBAddress;
-
- Trap macro _GetIndADB
-
- On entry: A0: pointer to parameter block
- D0: entry index number; range = 1..CountADBs (byte)
-
- Parameter block
- <-- 0 device type byte (handler ID)
- <-- 1 original ADB address byte
- <-- 2 service routine address pointer (compRout)
- <-- 6 data area address pointer (data)
-
- On exit: D0: positive value: current ADB address (byte)
- negative value: error code (byte)
-
- GetIndADB returns information from the ADB device table entry whose index number is
- given by devTableIndex. ADBDataBlock has this form:
-
- TYPE ADBDataBlock =
- PACKED RECORD
- devType: SignedByte; {device type (handler ID)}
- origADBAddr: SignedByte; {original ADB address}
- dbServiceRtPtr: Ptr; {service routine address (compRout)}
- dbDataAreaAddr: Ptr {data area address (data)}
- END;
-
- GetIndADB returns the current ADB address of the device. If it is unable to complete
- execution successfully, GetIndADB returns a negative value.
-
- FUNCTION GetADBInfo (VAR info: ADBDataBlock; ADBAddr: ADBAddress) : OsErr;
-
- Trap macro _GetADBInfo
-
- On entry: A0: pointer to parameter block
- D0: ADB address of the device (byte)
-
- Parameter block
- <-- 0 device handler ID byte
- <-- 1 original ADB address byte
- <-- 2 service routine address pointer (compRout)
- <-- 6 data area address pointer (data)
-
- On exit: D0: result code (byte)
-
- GetADBInfo returns information from the ADB device table entry of the device whose
- ADB address is given by ABDAddr. The structure of ADBDataBlock is given above under
- “GetIndADB”.
-
- Result codes noErr No error
-
- FUNCTION SetADBInfo (VAR info: ADBSetInfoBlock; ADBAddr: ADBAddress) : OsErr;
-
- Trap macro _SetADBInfo
-
- On entry: A0: pointer to parameter block
- D0: ADB address of the device (byte)
-
- Parameter block
- --> 0 service routine address pointer (compRout)
- --> 4 data area address pointer (data)
-
- On exit: D0: result code (byte)
-
- SetADBInfo sets the service routine address and the data area address in the ADB
- device table entry for the device whose ADB address is given by ABDAddr. ADBSetInfoBlock
- has this form:
-
- TYPE ADBSetInfoBlock =
- RECORD
- siServiceRtPtr: Ptr; {service routine address (compRout)}
- siDataAreaAddr: Ptr {data area address (data)}
- END;
-
- Result codes noErr No error
-
- Warning: You should send a Flush command to the device after calling it
- with SetADBInfo, to prevent it sending old data to the new data
- area address.
-
- _______________________________________________________________________________
-
-
- æKY Writing…ADB…Device…Drivers
- æC »WRITING ADB DEVICE DRIVERS AppleDesktopBus
- _______________________________________________________________________________
-
- Drivers for devices connected to the ADB have the following special requirements:
-
- • Each ADB device driver must reside in a resource of type 'ADBS'.
- (An example 'ADBS' resource is available in MacDTS Sample Code
- “TbltDrvr.”) This type has two sections: initialization and driver code.
- • The initialization section of each ADB device driver must support the
- installation procedure described below.
-
- When the system calls an ADB device driver, it passes it the following values:
-
- • Register A0 points to the data buffer, which is formatted as a
- Pascal string (buffer).
- • Register A1 points to the driver’s completion routine (compRout).
- • Register A2 points to the optional data area (data).
- • Register D0 contains the ADB command that resulted in the driver
- being called (commandNum).
-
- The ADB driver should handle the ADB command passed to it and store any resulting
- input data by an appropriate action, such as by posting an event or moving the cursor.
-
- Note: Events posted from keyboards connected to the ADB now have an
- expanded structure. For more information, see the Toolbox Event
- Manager chapter.
-
- _______________________________________________________________________________
-
- »Installing an ADB Driver
-
- The Start Manager (described in this volume) finds all the ADB devices connected to
- the system and places their device types and ADB addresses in the ADB device table.
- It then calls the initialization section of each ADB device driver by executing the
- initialization code in its 'ADBS' resource.
-
- As a minimum, the initialization section of each ADB device driver must do the following:
-
- • The driver must allocate all the memory required by the driver code
- in one or more nonrelocatable blocks in the system heap area.
- • The driver must install its own preprocessing/postprocessing routine
- (if any) as described above under “ADBReInit”.
- • Finally, the driver must initialize the service routine address and
- data area address of its entry in the ADB device table, using SetADBInfo.
-
- _______________________________________________________________________________
-
-
- æKY Summary…of…the…ADB
- æC »SUMMARY OF THE ADB MANAGER AppleDesktopBus
- _______________________________________________________________________________
-
- Data Types
-
- TYPE
- ADBDataBlock =
- PACKED RECORD
- devType: SignedByte; {Handler ID}
- origADBAddr: SignedByte; {original ADB address}
- dbServiceRtPtr: Ptr; {service routine address (compRout)}
- dbDataAreaAddr: Ptr {data area address (area)}
- END;
-
- ADBSetInfoBlock =
- RECORD
- siServiceRtPtr: Ptr; {service routine address}
- siDataAreaAddr: Ptr {data area address}
- END;
-
- _______________________________________________________________________________
-
- Routines
-
- Initializing the ADB Manager
-
- PROCEDURE ADBReInit;
-
- Communicating Through the ADB
-
- FUNCTION ADBOp (data: Ptr; compRout: ProcPtr; buffer: Ptr;
- commandNum: INTEGER) : OSErr;
-
- Getting ADB Device Information
-
- FUNCTION CountADBs: INTEGER;
- FUNCTION GetIndADB (VAR info: ADBDataBlock;
- devTableIndex: INTEGER) : ADBAddress;
- FUNCTION GetADBInfo (VAR info: ADBDataBlock; ADBAddr: ADBAddress) : OsErr;
-
- Setting ADB Device Information
-
- FUNCTION SetADBInfo (VAR info: ADBSetInfoBlock; ADBAddr: ADBAddress) : OsErr;
-
- _______________________________________________________________________________
-
- Assembly-Language Information
-
- Variables
-
- JADBProc Pointer to ADBReInit preprocessing/postprocessing routine
- KbdLast ADB address of the keyboard last used (byte)
- KbdType Keyboard type of the keyboard last used (byte)
-
- Routines
-
- Trap macro On entry On Exit
-
- _ADBReInit
-
- _ADBOp A0: pointer to parameter block D0: result code (byte)
- buffer (pointer)
- compRout (pointer)
- data (pointer)
- D0: commandNum (byte)
-
- _CountADBs D0: result code (byte)
-
- _GetIndADB A0: pointer to parameter block D0: positive value:
- device type (byte) current ADB
- original ADB address (byte) address (byte)
- service routine address (pointer) negative value:
- data area address (pointer) error code (byte)
- D0: entry index number;
- range = 1..CountADBs (byte)
-
- _GetADBInfo A0: pointer to parameter block D0: result code (byte)
- device handler ID (byte)
- original ADB address (byte)
- service routine address (pointer)
- data area address (pointer)
- D0: current ADB address of the device (byte)
-
- _SetADBInfo A0: pointer to parameter block D0: result code (byte)
- service routine address (pointer)
- data area address (pointer)
- D0: current ADB address of the device (byte)
-
- Further Reference:
- _______________________________________________________________________________
- Toolbox Event Manager
- Technical Note #143, Don’t Call ADBReInit on the SE with System 4.1
- Technical Note #160, Key Mapping
- Technical Note #206, Space Aliens Ate My Mouse
- “Macintosh Family Hardware Reference”
-
-
- æKY AppleEventManager
- æC
- _______________________________________________________________________________
-
- THE APPLE EVENT MANAGER
- _______________________________________________________________________________
-
- About…the…Apple…Event…Manager…Chapter…Volume…VI
- About…the…Apple…Event…Manager…Volume…VI
- Introduction…to…Apple…Events…Volume…VI
- Types…of…Apple…Events
- Components…of…Apple…Events
- Data…Structures…Within…Apple…Events
- Responding…to…Apple…Events
- Requesting…Services…Through…Apple…Events
- Using…the…Apple…Event…Manager…Volume…VI
- Accepting…an…Apple…Event
- Installing…Entries…Into…the…Apple…Event…Dispatch…Tables
- Handling…the…Required…Apple…Events
- Required…Apple…Events
- Handling…the…Open…Application…Event
- Handling…the…Open…Documents…Event
- Handling…the…Print…Documents…Event
- Handling…the…Quit…Application…Event
- Handling…Apple…Events…Sent…by…the…Edition…Manager
- Handling…the…Create…Publisher…Event
- Getting…Data…out…of…an…Apple…Event
- Getting…Data…out…of…a…Parameter
- Getting…Data…out…of…an…Attribute
- Getting…Data…out…of…a…Descriptor…List
- Writing…Apple…Event…Handlers
- Replying…to…an…Apple…Event
- Disposing…of…Apple…Event…Data…Structures
- Interacting…With…the…User
- Creating…an…Apple…Event
- Adding…Parameters…to…an…Apple…Event
- Specifying…a…Target…Address
- Sending…an…Apple…Event
- Dealing…With…Timeouts
- Writing…an…Idle…Function
- Writing…a…Reply…Filter…Function
- Writing…and…Installing…Coercion…Handlers
- The…Application…Died…Event
- Apple…Event…Manager…Routines…Volume…VI
- Creating…and…Managing…the…Apple…Event…Dispatch…Tables
- Dispatching…Apple…Events
- Getting…Parameters…and…Attributes…From…Apple…Events
- Counting…the…Items…in…Descriptor…Lists
- Getting…Items…From…Descriptor…Lists
- Getting…Data…From…AE…Records
- Requesting…User…Interaction
- Requesting…More…Time…to…Respond…to…Apple…Events
- Suspending…and…Resuming…Apple…Event…Handling
- Creating…Apple…Events
- Creating…and…Duplicating…Descriptor…Records
- Creating…Descriptor…Lists…and…AE…Records
- Adding…Items…to…Descriptor…Lists
- Adding…Data…to…AE…Records
- Adding…Parameters…and…Attributes…to…Apple…Events
- Sending…Apple…Events
- Getting…the…Sizes…and…Descriptor…Types…of…Descriptor…Records
- Deleting…Descriptor…Records
- Deallocating…Memory…for…Descriptor…Records
- Coercing…Descriptor…Types
- Creating…and…Managing…the…Coercion…Handler…Tables
- Creating…and…Managing…the…Special…Handler…Tables
- Summary…of…the…Apple…Events…Manager…Volume…VI
- Apple…Events…Manager…Constants
- Apple…Events…Manager…Data…Types
- Apple…Events…Manager…Routines…Summary
- Apple…Events…Manager…Result…Codes
- Apple…Events…Manager…Assembly-Language…Information
- _______________________________________________________________________________
-
-
-
- æKY About…the…Apple…Event…Manager…Chapter…Volume…VI
- æC »About the Apple Event Manager Chapter Volume VI The Apple Event Manager
- _______________________________________________________________________________
-
- This chapter describes Apple® events and how your application can use the Apple
- Event Manager to receive and process the required set of Apple events sent by
- the Finder™. This chapter also describes how to use the Apple Event Manager to
- send Apple events to other applications and how to process Apple events received
- from other applications.
-
- As explained in the Event Manager chapter in this volume, the Event Manager in
- system software version 7.0 introduces high-level events, along with a number of
- new Event Manager routines that let applications communicate with each other by
- sending high-level events. Using Event Manager routines, your application can
- create and process its own high-level events.
-
- However, effective interapplication communication requires that applications
- agree on a standard set of conventions—a common vocabulary. To provide such a
- standard, Apple Computer, Inc., has defined a protocol called the Apple Event
- Interprocess Messaging Protocol (AEIMP). High-level events that adhere to this
- protocol are called Apple events. You can help ensure effective communication
- with other applications by using this protocol..
-
- System software uses Apple events to communicate information to your
- application; you should support the required set of Apple events sent by the
- Finder to your application. In addition, you can support Apple events that are
- common to many applications. Using the routines of the Apple Event Manager, you
- can use Apple events to communicate with other applications in a standard way.
- Using Apple events to ensure better cooperation between your application and
- other applications helps users to get the most out of any one application or to
- use the best features from many applications—in effect, combining the features
- of many applications to achieve the desired result.
-
- By following the standards specified by AEIMP, you can also define your own
- Apple events. You can choose to publish these so that other applications can use
- them, or you may choose to keep them unpublished for exclusive use by your own
- applications.
-
- The Apple Event Manager is available only in system software version 7.0. To
- determine whether the Apple Event Manager is available, use the Gestalt function
- described in the Compatibility Guidelines chapter of this volume.
-
- The interapplication communications architecture of system software version 7.0
- consists of three main components: the Apple Event Manager, the Event Manager,
- and the Program-to-Program Communications (PPC) Toolbox. See the Introduction to
- the System Software Version 7.0 Environment chapter in this volume for an
- overview of the relationships among these components. If you intend to use
- high-level events that do not rely on AEIMP, read the Event Manager chapter of
- this volume. This chapter describes the information you need to know to support
- Apple events in your application. To allow your application to send Apple events
- to applications on remote computers, you may wish to use the PPCBrowser
- function, which is described in the Program-to-Program Communications Toolbox
- chapter of this volume.
-
- While the Apple events used by the Edition Manager are discussed in this
- chapter, you must refer to the Edition Manager chapter of this volume for a full
- discussion of how to implement the Edition Manager’s publish and subscribe
- features.
-
- For descriptions of all publicly available Apple events, see the Apple Event
- Registry, available from Macintosh® Developer Technical Support.
-
- _______________________________________________________________________________
-
- æKY About…the…Apple…Event…Manager…Volume…VI
- æC »About the Apple Event Manager Volume VI The Apple Event Manager
- _______________________________________________________________________________
-
- Apple events provide your application with a standard mechanism for
- communicating with other applications. You can use Apple events and the Apple
- Event Manager to
-
- • respond to the required Apple events (Open Application, Open Documents,
- Print Documents, and Quit Application) that are sent by the Finder
-
- • respond to the Apple events sent by the Edition Manager and allow users to
- share data among documents created by multiple applications
-
- • provide services to other applications
-
- • request services from other applications
-
- By supporting the required Apple events, your application can take advantage of
- the more reliable launch and termination mechanisms built into system software
- version 7.0. You can also take advantage of the services provided by the Edition
- Manager by responding to the Apple events sent by the Edition Manager. These and
- additional core Apple events can be used by nearly all applications to
- communicate with system software or with other applications.
-
- You can also support functional-area Apple events related to your application in
- order to provide services to other applications or to request services from
- other applications. Finally, if your application defines Apple events for all
- the actions that a user can perform, you can record user actions by generating
- the corresponding Apple event for each action, saving a copy of the Apple event,
- and then sending the Apple event to your own application for handling. Apple
- events that are recorded in this way can later be played back to automate tasks
- previously performed by the user.
-
- To support Apple events in your application, you must
-
- • decide which Apple events (in addition to the required ones) to support
-
- • set bits in the 'SIZE' resource to indicate that your application supports
- high-level events
-
- • create an Apple event dispatch table
-
- • include code to handle high-level events in your main event loop
-
- • handle the Apple events your application receives and wishes to support
-
- • create the Apple events you wish your application to generate
-
- This chapter begins with an introduction to Apple events and then describes
-
- • the required Apple events that your application must support to be
- 7.0-friendly
-
- • how to use the Apple Event Manager to send and process Apple events
- _______________________________________________________________________________
-
- æKY Introduction…to…Apple…Events…Volume…VI
- æC »Introduction to Apple Events Volume VI The Apple Event Manager
- _______________________________________________________________________________
-
- Applications typically use Apple events to request services from and provide
- services to other applications. For example, the Open Documents event, sent by
- the Finder, requests that your application open specified documents. When your
- application supports this Apple event, it should respond by opening those
- documents in the manner that your application normally opens documents.
-
- A transaction involving Apple events is initiated by a client application, which
- sends an Apple event to request a service (for example, printing a list of
- files, spell-checking a list of words, or performing a numerical calculation).
- The application providing the service is called a server application. These
- applications can reside on the same local computer or on remote computers
- connected to a network.
-
- Figure 6-1 shows a common Apple event, the Open Documents event. You see that
- the Finder application is the client; it requests that the SurfWriter
- application open the documents named Dec. Invoice and Nov. Invoice. The
- SurfWriter application responds to the Finder’s request by opening windows
- containing the specified documents.
-
- ¿ Figure 6-1 An Open Documents event ø
-
- The Finder is also the source application of the Open Documents event. A source
- application is one that sends an Apple event to another application or to
- itself. In Figure 6-1, the SurfWriter application is the target application of
- the event. The target application is the one addressed to receive the Apple
- event. The terms client application and source application are not always
- synonymous, nor are the terms server application and target application.
- Typically, an Apple event client sends an Apple event requesting a service from
- an Apple event server; in this case, the server is the target application of the
- Apple event. The Apple event server may send back a different Apple event as a
- response—in which case, the client becomes the target of the responding Apple
- event.
-
- _______________________________________________________________________________
-
- æKY Types…of…Apple…Events
- æC »Types of Apple Events The Apple Event Manager
- _______________________________________________________________________________
-
- Apple events fall into one of several broad categories.
-
- • Required Apple events consist of four core Apple events that the Finder
- sends
- to applications. These events are called Open Documents, Open Application,
- Print Documents, and Quit Application. They are a subset of the core Apple
- events and are described in detail later in this chapter.
-
- • Core Apple events are used by nearly all applications to communicate. The
- suite
- of core Apple events is described in the Apple Event Registry; Apple
- recommends that all applications support the core Apple events.
-
- • Functional-area Apple events are supported by applications with related
- features. Apple events related to text manipulation for word-processing
- applications and Apple events related to graphics manipulation for drawing
- applications are examples of functional-area Apple events. Functional-area
- Apple events are defined by Apple in consultation with interested
- developers
- and are published in the Apple Event Registry. Apple recommends that all
- developers support functional-area Apple events appropriate for their types
- of
- applications.
-
- • Custom Apple events are defined by a developer for use by the developer’s
- own
- applications. You should register all of your custom Apple events with
- Macintosh Developer Technical Support. You can choose to publish your Apple
- events in the Apple Event Registry so that other applications can share
- them, or
- you may choose to keep them unpublished for exclusive use by your own
- applications.
- _______________________________________________________________________________
-
- æKY Components…of…Apple…Events
- æC »Components of Apple Events The Apple Event Manager
- _______________________________________________________________________________
-
- An Apple event consists of attributes (which identify the Apple event and denote
- its task) and, often, parameters (which contain data to be used by the target
- application). An application uses the Apple Event Manager to create an Apple
- event. Using arguments you pass to the AECreateAppleEvent function and to other
- Apple Event Manager routines, the Apple Event Manager constructs the necessary
- data structures containing attributes and parameters and converts these
- structures into an Apple event. Applications must use the Apple Event Manager’s
- AESend function to transmit the Apple event. After receiving an Apple event,
- applications must use Apple Event Manager routines to extract the attributes and
- parameters of the event.
-
- Attributes are a fundamental component of Apple events. Apple event attributes
- are records that identify the event class, event ID, target application, and
- other characteristics of an Apple event. Taken together, the attributes of an
- Apple event denote the task to be performed on any data specified in the Apple
- event’s parameters. You do not have any direct way to access the data stored in
- these records. You must use Apple Event Manager routines to extract or specify
- the attributes.
-
- An Apple event parameter is a record containing data that the target application
- uses. Unlike Apple event attributes (which contain information that can be used
- by both the Apple Event Manager and the target application), Apple event
- parameters contain data used only by the target application. For example, an
- attribute like the event ID is used by the Apple Event Manager to call a handler
- from the server application’s dispatch table, and the server application must
- have a handler to process the event identified by that attribute. By comparison,
- the list of documents contained in a parameter to an Open Documents event is
- used only by the server application. As with attributes, you do not have any
- direct way to access the data structure of a parameter. You have to use Apple
- Event Manager functions to extract or put data into parameters.
-
- Note that Apple event parameters are different from the parameters of Apple
- Event Manager functions. Apple event parameters are records private to the Apple
- Event Manager; function parameters are arguments you pass to the function or
- that the function returns to you. You typically specify the Apple event
- parameters (as well as the attributes) in parameters to Apple Event Manager
- functions. For example, the AEGetParamPtr function uses a buffer to return the
- data contained in an Apple event parameter. You specify which Apple event
- parameter in one of the parameters of the AEGetParamPtr function.
-
- Apple events are identified by their event class and event ID attributes. The
- event class is the attribute that identifies a group of related Apple events.
- The event class appears in the message field of the event record for an Apple
- event. For example, the four required Apple events (in fact, all core Apple
- events) have the value 'aevt' in the message fields of their event records. The
- value 'aevt' can also be represented by the kCoreEventClass constant. Several
- event classes are shown here.
-
- Event class Value Description
-
- kCoreEventClass 'aevt' A core Apple event
- kAEFinderEvents 'FNDR' An event that the Finder accepts
- kSectionEventMsgClass 'sect' An event sent by the Edition Manager
-
- The event ID is the attribute that identifies the particular Apple event within
- its event class. In conjunction with the event class, the event ID uniquely
- identifies the Apple event and communicates what action the Apple event should
- perform. (The event IDs appear in the where field of the event record for an
- Apple event.) For example, the event ID of an Open Documents event has the value
- 'odoc' (which can also be represented by the kAEOpenDocuments constant). The
- kCoreEventClass constant in combination with the kAEOpenDocuments constant
- identifies the Open Documents event to the Apple Event Manager.
-
- Shown here are the event IDs for the four required Apple events.
-
- Event ID Value Description
-
- kAEOpenApplication 'oapp' Open your application
- kAEOpenDocuments 'odoc' Open documents
- kAEPrintDocuments 'pdoc' Print documents
- kAEQuitApplication 'quit' Quit your application
-
- The target application’s address is another required attribute. As previously
- described, the target application is the one addressed to receive the Apple
- event. Your application can send an Apple event to itself or to another
- application (on the same computer or on a remote computer connected to the
- network).
-
- As with attributes, there are various types of Apple event parameters. A direct
- parameter contains the data to be acted upon by the server application. For
- example, a list of documents is contained in the direct parameter of the Print
- Documents event. Direct parameters are usually required parameters—parameters
- that the server application needs in order to carry out the task denoted by the
- Apple event. Some Apple events also take additional parameters, which the server
- application uses in addition to the data specified in the direct parameter. For
- example, an Apple event for arithmetic operations may include additional
- parameters that specify operands in an equation. Additional parameters may be
- required or optional.
-
- An optional parameter is a supplemental parameter that also can be used to
- specify data to the server application. Optional parameters need not be included
- in an Apple event; default values for optional parameters are part of the event
- definition. The server application that handles the event must supply default
- values if the optional parameters are omitted.
-
- Figure 6-2 shows in greater detail the components of the Open Documents event
- that was introduced in Figure 6-1.
-
- ¿ Figure 6-2 Major components of an Open Documents event ø
-
- To process the information contained in the Open Documents event, the SurfWriter
- application uses the AEProcessAppleEvent function. The AEProcessAppleEvent
- function provides an easy way for your application to identify the event class
- and event ID of the Apple event and to direct the Apple Event Manager to call
- the code in your program that handles the Apple event.
- _______________________________________________________________________________
-
- æKY Data…Structures…Within…Apple…Events
- æC »Data Structures Within Apple Events The Apple Event Manager
- _______________________________________________________________________________
-
- Applications must use Apple Event Manager functions to create and send an Apple
- event. The Apple Event Manager constructs its own internal data structures to
- contain the information in an Apple event. To gain access to this data, the
- target application also must use Apple Event Manager functions. Neither the
- sender nor the receiver of an Apple event can directly manipulate the data
- inside an Apple event; each must rely on Apple Event Manager functions to do so.
- This section describes the data structures that the Apple Event Manager uses to
- create and to process Apple events.
-
- Descriptor records are the fundamental structures from which Apple events are
- constructed. A descriptor record is a data structure of type AEDesc; it consists
- of a handle to data and a descriptor type that identifies the type of the data
- referred to by the handle.
-
- TYPE AEDesc =
- RECORD
- descriptorType: DescType; {type of data being passed}
- dataHandle: Handle {handle to data being passed}
- END;
-
- The data referred to by the dataHandle field in the descriptor record is private
- to the Apple Event Manager. You can supply or extract this data only by using
- Apple Event Manager routines.
-
- The descriptor type is a structure of type DescType, which in turn is of data
- type ResType—that is, a four-character string. Constants are usually used in
- place of these four-character strings when referring to descriptor types.
- Descriptor types represent various data types. Here is a list of descriptor type
- constants, their values, and the types of data they represent.
-
- Descriptor type Value Description
-
- typeBoolean 'bool' Boolean value
- typeChar 'TEXT' Unterminated string
- typeSMInt 'shor' 16-bit integer
- typeInteger 'long' 32-bit integer
- typeSMFloat 'sing'; SANE Single
- typeFloat 'doub'; SANE Double
- typeLongInteger 'long' 32-bit integer
- typeShortInteger 'shor' 16-bit integer
- typeLongFloat 'doub' SANE Double
- typeShortFloat 'sing' SANE Single
- typeExtended 'exte' SANE Extended
- typeComp 'comp' SANE Comp
- typeMagnitude 'magn' Unsigned 32-bit integer
- typeAEList 'list' List of descriptor
- records
- typeAERecord 'reco' List of keyword-specified
- descriptor records
- typeAppleEvent 'aevt' Apple event record
- typeTrue 'true' TRUE Boolean value
- typeFalse 'fals' FALSE Boolean value
- typeAlias 'alis' Alias record
- typeEnumerated 'enum' Enumerated data
- typeType 'type' Four-character code for
- event class or event
- ID
- typeAppParameters 'appa' Process Manager launch parameters
- typeProperty 'prop' Apple event property
- typeFSS 'fss ' File system
- specification
- typeKeyword 'keyw' Apple event keyword
- typeSectionH 'sect' Handle to a section record
- typeTemporaryID 'tid ' Temporary ID
- typeWildCard '****' Matches any type
- typeApplSignature 'sign' Application signature
- typeSessionID 'ssid' Session ID
- typeTargetID 'targ' Target ID record
- typeProcessSerialNumber 'psn ' Process serial number
- typeNull 'null' NULL or nonexistent
- data
-
- Figure 6-3 illustrates a descriptor record with a descriptor type of typeType,
- which specifies that the data in the descriptor record must consist of a
- four-character code. The data in this particular descriptor record is specified
- by the constant kCoreEventClass, whose value is 'aevt'.
-
- ¿ Figure 6-3 A descriptor record with event class data ø
-
- A descriptor record that contains the address of the target or source of an
- Apple event is called an address descriptor record.
-
- TYPE AEAddressDesc = AEDesc; {address descriptor record}
-
- As you will see later, the address can be specified as an application signature,
- a process serial number, a session ID, a target ID record, or a data type that
- you define.
-
- Data for attributes and parameters are contained in descriptor records. The
- attributes and parameters themselves are identified by keywords. The AEKeyword
- data type is defined as a four-character code.
-
- TYPE AEKeyword = PACKED ARRAY[1..4] OF Char;
- {keyword for a descriptor }
- { record}
-
- Constants are typically used for keywords. Shown here is a list of these keyword
- constants, their four-character codes, and the attributes and parameters they
- represent.
-
- Attribute keyword Value Description
-
- keyAddressAttr 'addr' Address of target application
- keyEventClassAttr 'evcl' Event class of Apple event
- keyEventIDAttr 'evid' Event ID of Apple event
- keyEventSourceAttr 'esrc' Source of the Apple event
- keyInteractLevelAttr 'inte' Settings for allowing the Apple
- Event
- Manager to
- bring a
- server
-
- to the
- foreground
- keyMissedKeywordAttr 'miss' First required parameter remaining in
- an
- Apple
- event
- keyOptionalKeywordAttr 'optk' List of optional parameters for the
- Apple
- event
- keyReturnIDAttr 'rtid' Return ID for reply Apple
- event
- keyTimeoutAttr 'timo' Length of time in ticks that the
- client will
- wait for a
- reply or a
- result
- from the
- server
- keyTransactionIDAttr 'tran' Transaction ID identifying a series
- of Apple
- events
-
- Parameter keyword Value Description
-
- keyDirectObject '––––' Direct parameter
- keyErrorNumber 'errn' Error number parameter
- keyErrorString 'errs' Error string parameter
- keyProcessSerialNumber 'psn ' Process serial number parameter
-
- A data structure of type AEKeyDesc consists of a keyword and a descriptor
- record. This data structure, called a keyword-specified descriptor record, is
- used by the Apple Event Manager to fully identify and describe an attribute or a
- parameter of an Apple event.
-
- TYPE AEKeyDesc = {keyword-specified descriptor record}
- RECORD
- descKey: AEKeyword; {keyword}
- descContent: AEDesc {descriptor record};
- END;
-
- Figure 6-4 illustrates a keyword-specified descriptor record for the event class
- attribute of an Open Documents event. The keyEventClassAttr keyword identifies
- its descriptor record as containing event class data. The data is of the
- typeType descriptor type, and the data identifies the event class as
- kCoreEventClass.
-
- ¿ Figure 6-4 A keyword-specified descriptor record for the event class
- attribute of an Open Documents event ø
-
- When extracting data from an Apple event, you use Apple Event Manager functions
- to return data in a buffer specified by a pointer, or to return descriptor
- records containing the data, or to return lists of descriptor records (called
- descriptor lists) containing the data. As previously noted, the descriptor
- record (of data type AEDesc) is the fundamental structure in Apple events, and
- it contains a handle to data. A descriptor list is a data structure of type
- AEDescList defined by the data type AEDesc—that is, a descriptor list is a
- descriptor record that contains a list of other descriptor records.
-
- TYPE AEDescList = AEDesc; {list of descriptor records}
-
- An example of a descriptor list that you will be using is the direct parameter
- for the Open Documents event. As illustrated in Figure 6-5, this descriptor list
- is a list of descriptor records that contain alias records to filenames. (The
- Alias Manager chapter of this volume describes alias records in detail.)
-
- ¿ Figure 6-5 A descriptor list for a list of aliases ø
-
- Closely related to a descriptor list is a structure of data type AERecord; in
- fact, it is defined by the data type AEDescList.
-
- TYPE AERecord = AEDescList; {list of keyword-specified }
- { descriptor records}
-
- While a descriptor list is a descriptor record that contains a list of other
- descriptor records, an AE record of data type AERecord contains a list of
- keyword-specified descriptor records describing parameters. A descriptor list of
- data type AERecord contains no attributes, only parameters.
-
- There is one final data structure to consider: the Apple event record. An Apple
- event record is a structure of data type AppleEvent defined as an AE record. It
- is used for describing a full-fledged Apple event.
-
- TYPE AppleEvent = AERecord; {list of attributes and parameters }
- { necessary for an Apple event}
-
- An Apple event record is basically a descriptor record (of descriptor type
- typeAppleEvent) with a handle to a list of keyword-specified descriptor records.
- These descriptor records describe the attributes and parameters for an Apple
- event. When you use the AECreateAppleEvent function, the Apple Event Manager
- creates an Apple event record containing the attributes for an Apple event’s
- event class, event ID, target address, return ID, and transaction ID. You then
- use Apple Event Manager functions such as AEPutParamDesc to add parameters to
- the Apple event. Figure 6-6 shows an example of an Apple event—a structure
- containing a list of keyword-specified descriptor records that name the
- attributes and parameters of an Open Documents event.
-
- ¿ Figure 6-6 Data structures within an Open Documents event ø
-
- The internal structure of an Apple event record is nearly identical to an AE
- record. They differ in the content referred to by the data handles that they
- contain: the former has a list of attributes and, possibly, parameters referred
- by its handle; the latter contains only parameters. However, you can pass an
- Apple event record to any Apple Event Manger function that expects an AE record.
- Since both are structures of data type AEDescList, which is derived from the
- data type AEDesc, you can pass Apple event records, AE records, descriptor
- lists, and descriptor records to any Apple Event Manager functions that expect
- records of data type AEDesc.
-
- The data in Apple event records, AE records, and descriptor lists—all of which
- are descriptor records—is private to the Apple Event Manager. The Apple Event
- Manager maintains these different data structures because it stores different
- kinds of information in their handles. Although all the information you need is
- available by calling the appropriate Apple Event Manager functions, the Apple
- Event Manager needs a way to tell these different descriptor records apart. It
- does this by looking at their data types.
- _______________________________________________________________________________
-
- æKY Responding…to…Apple…Events
- æC »Responding to Apple Events The Apple Event Manager
- _______________________________________________________________________________
-
- A client application uses the Apple Event Manager to create and send an Apple
- event requesting a service. A server application responds by using the Apple
- Event Manager to process the Apple event, to extract data from the attributes
- and parameters of the Apple event, and to return a result to the client
- application. The server provides its own routines for performing the action
- requested by the client’s Apple event.
-
- As its first step in supporting Apple events, your application must be able to
- respond to the required Apple events sent by the Finder. If you plan to
- implement publish and subscribe capabilities, your application must respond to
- the Apple events sent by the Edition Manager. You can also respond to Apple
- events sent by your own application or by other applications. This section
- provides a quick overview of the steps your application takes in responding to
- Apple events.
-
- To respond to Apple events, your application must
-
- • test for high-level events in its event loop
-
- • use the AEProcessAppleEvent function to process Apple events
-
- • provide handler routines for the Apple events it supports
-
- • use Apple Event Manager functions to extract the parameters and attributes
- from Apple events
-
- • use the AEInteractWithUser function—if your application requires input from
- the user when your application is responding to an Apple event—to bring
- your
- application to the foreground to interact with the user
-
- • return a result for the client
-
- Note that in order for your application to respond to Apple events sent from
- remote computers, the user of your application must allow network users to link
- to your application. The user does this by selecting your application from the
- Finder and choosing Sharing from the File menu and then clicking the Allow
- Remote Program Linking checkbox. If the user has not yet started program
- linking, the Sharing command offers to display the Sharing Setup control panel
- so that the user can start program linking. The user must also authorize remote
- users for program linking by using the Users and Groups control panel. Program
- linking and setting up authenticated sessions are described in the
- Program-to-Program Communications chapter in this volume.
-
- An Apple event (like all high-level events) is identified by a message class of
- kHighLevelEvent in the what field of the event record. You test the what field
- of the event record to determine whether an event is a high-level event. If the
- what field contains the kHighLevelEvent constant and your application defines
- any high-level events other than Apple events, test the message field of the
- event record to determine whether the high-level event is something other than
- an Apple event. If the high-level event is not one that you’ve defined for your
- application, assume that it is an Apple event. (Note that you are encouraged to
- use Apple events instead of defining your own high-level events whenever
- possible.)
-
- After determining that an event is an Apple event, use the AEProcessAppleEvent
- function to let the Apple Event Manager identify the event. Figure 6-7 shows how
- the SurfWriter application accepts and begins to process an Apple event sent by
- the Finder.
-
- ¿ Figure 6-7 Accepting and processing an Open Documents event ø
-
- The AEProcessAppleEvent function begins processing the Apple event. The
- AEProcessAppleEvent function identifies the Apple event by examining the data in
- the event class and event ID attributes. The AEProcessAppleEvent function in
- turn uses that data to call the Apple event handler that your application
- provides for that event. An Apple event handler is a function that extracts the
- pertinent data from the Apple event, performs the action requested by the Apple
- event, and returns a result. For example, if the event has an event class of
- kCoreEventClass and an event ID of kAEOpenDocuments, the AEProcessAppleEvent
- function calls your application’s routine for handling the Open Documents event.
-
- You install Apple event handlers by using the AEInstallEventHandler function.
- This function creates an Apple event dispatch table that the Apple Event Manager
- uses to map Apple events to handlers in your application. After being called by
- the AEProcessAppleEvent function to process an Apple event, the Apple Event
- Manager reads the Apple event dispatch table and, if your application has
- installed a handler for that Apple event, calls your handler to finish
- responding to the event. Figure 6-8 shows how the flow of control passes from
- your application to the Apple Event Manager and back to your application.
-
- ¿ Figure 6-8 The Apple Event Manager calling the handler for an Open Documents
- event ø
-
- Your Apple event handlers must generally perform the following tasks:
-
- • extract the parameters and attributes for the Apple event
-
- • check that all the required parameters have been extracted
-
- • set user interaction level preferences if necessary and, if your application
- needs
- to interact with the user, use the AEInteractWithUser function to bring it
- to the
- foreground
-
- • perform the action requested by the Apple event
-
- • dispose of any copies of descriptor records that have been created
-
- • return a result for the client
-
- You must use Apple Event Manager functions to extract the data from Apple
- events. You can also use Apple Event Manager functions to get data out of
- descriptor records, descriptor lists, and AE records. Most of these routines are
- available in two forms: one that uses a buffer to return a copy of the desired
- data and one that returns a copy of the descriptor record containing the data.
- The following list shows the main functions you can use to access the data of an
- Apple event.
-
- Function Description
-
- AEGetParamPtr Uses a buffer to return the data contained in a
- parameter; used, for example,
- to extract the result code
- from the keyErrorNumber
- parameter of a reply Apple
- event.
-
- AEGetParamDesc Returns the descriptor record or descriptor list
- for a
- parameter; used, for example,
- to extract the descriptor
- list for a list of alias
- records specified in the direct
- parameter of the Open Documents
- event.
-
- AEGetAttributePtr Uses a buffer to return the data contained in an
- attribute;
- used, for example, to determine
- the source of an Apple
- event by extracting the data
- from the
- keyEventSourceAttr attribute.
-
- AEGetAttributeDesc Returns the descriptor record for a parameter;
- used, for
- example, to make a copy of a
- descriptor record
- containing the address of an
- application.
-
- AECountItems Returns the number of descriptor records in a
- descriptor
- list; used, for example, to
- determine the number of alias
- records for documents specified
- in the direct parameter
- of the Open Documents event.
-
- AEGetNthPtr Uses a buffer to return the data for a
- descriptor record
- that is contained in a
- descriptor list; used, for
- example, to
- extract a document’s alias
- record from the descriptor list
- specified in the direct
- parameter of the Open Documents
- event.
-
- AEGetNthDesc Returns a descriptor record from a descriptor
- list; used,
- for example, to get the
- descriptor record containing an
- alias record from the list
- specified in the direct parameter
- of the Open Documents event.
-
- You can specify the descriptor type of the resulting data for these functions;
- if this is different from the descriptor type of the attribute or parameter, the
- Apple Event Manager attempts to coerce it to the specified type. In the direct
- parameter of the Open Documents event, for example, each descriptor record in
- the descriptor list is an alias record; each alias record specifies a document
- to be opened. As explained in the File Manager chapter of this volume, all your
- application usually needs is the file system specification (FSSpec) record of
- the document. When you extract the descriptor from the descriptor list, you can
- request that the Apple Event Manager return the data to your application as a
- file system specification record instead of as an alias record.
-
- After extracting all known parameters, your handler should check that it
- retrieved all the required parameters by checking whether the
- keyMissedKeywordAttr attribute exists. If the attribute exists, then your
- handler has not retrieved all the required parameters, and it should return an
- error.
-
- In some cases, the server may need to interact with the user when it handles an
- Apple event. For example, your handler for the Print Documents event may need to
- display a print options dialog box and get settings from the user before
- printing. Your handler should always use the AEInteractWithUser function before
- displaying a dialog box or alert box or otherwise interacting with the user. By
- specifying one of these flags to the AESetInteractionAllowed function, you can
- set your application’s user interaction level preferences.
-
- Flag Description
-
- kAEInteractWithSelf User interaction with your server application in
- response to an Apple event
- may be allowed only when
- the client application is
- your own application—that is,
- only when your application is
- sending the Apple event
- to itself.
-
- kAEInteractWithLocal User interaction with your server application in
- response to an Apple event
- may be allowed only if the
- client application is on the
- same computer as your
- application; this is the
- default if the
- AESetInteractionAllowed
- function is not used.
-
- kAEInteractWithAll User interaction with your server application in
- response to an Apple event
- may be allowed for any
- client application on any
- computer.
-
- For a server application to allow user interaction in response to the client’s
- Apple event, two conditions must be met. First, the client application must
- request that your server application allow user interaction. Second, your server
- application must allow user interaction in response to the Apple event sent from
- that client application as described in the previous list. If these conditions
- are met and your application needs to interact with the user, the
- AEInteractWithUser function brings your application to the foreground if it
- isn’t already in the foreground. Your application can then display its dialog
- box or alert box or otherwise interact with the user. AEInteractWithUser brings
- your server application to the front either directly or after the user responds
- to a notification request.
-
- When your application acts on an Apple event, it should perform the standard
- action requested by that event. For example, if the Apple event is the Open
- Documents event, your application should open the specified documents in titled
- windows just as if the user had selected each document from the Finder and then
- chosen Open from the File menu. You should strive to create routines that can be
- called in response to both user events and Apple events. To do this, you need to
- isolate code for interacting with the user from the code that performs the
- requested action—such as opening a document. You then call the code that
- performs the requested action from your Apple event handler.
-
- When you extract a descriptor record by using the AEGetParamDesc,
- AEGetAttributeDesc, AEGetNthDesc, or AEGetKeyDesc functions, the Apple Event
- Manager creates a copy of the descriptor record for you to use. When your
- handler is finished using a copy of a descriptor record, you should dispose of
- it—and thereby deallocate the memory it uses—by calling the AEDisposeDesc
- function.
-
- The required Apple events ask your application to perform tasks—open your
- application, open or print documents, or quit your application. Other Apple
- events may ask your application to return data. For example, if your application
- is a spelling checker, the client probably expects data in the form of a list of
- misspelled words to be returned from your application. If a reply is requested,
- the Apple Event Manager prepares a reply Apple event for the client by passing a
- default reply Apple event to your handler. The default reply Apple event has no
- parameters when it is passed to your handler. Your handler can add any
- parameters to the reply Apple event. If your application is a spelling checker,
- for example, you can return a list of misspelled words in a parameter.
-
- Your handler routine should always set its function result either to noErr if it
- successfully handles the Apple event or to a nonzero result code if an error
- occurs. If an error occurs, the Apple Event Manager adds a keyErrorNumber
- parameter to the reply Apple event; this parameter contains the result code that
- your handler returns. The client should check whether the keyErrorNumber
- parameter exists to determine whether your handler performed the requested
- action. In addition to returning a result code, your handler can also return an
- error string in the keyErrorString parameter of the reply Apple event. The
- client can use this string in an error message to the user.
-
- If the source requested a reply, the Apple Event Manager returns the reply Apple
- event to the source. The reply Apple event is identified by the event class
- kCoreEventClass and by the event ID kAEAnswer. When you have finished using the
- reply Apple event, you should dispose of it—and thereby deallocate the memory it
- uses—by calling the AEDisposeDesc function.
-
- When your handler returns a result code to the Apple Event Manager, you have
- finished your response to the client’s Apple event. Figure 6-9 shows the entire
- process of responding to an Apple event. The next section describes how to send
- an Apple event.
-
- ¿ Figure 6-9 Responding to an Open Documents eventi.Open Documents event ø
-
- _______________________________________________________________________________
-
- æKY Requesting…Services…Through…Apple…Events
- æC »Requesting Services Through Apple Events The Apple Event Manager
- _______________________________________________________________________________
-
- Your application can use Apple events to request services from other
- applications. By using Finder events, for example, your application can simulate
- the behavior of the Finder by requesting that the Finder perform such operations
- as launching an application on your behalf. By using functional-area Apple
- events, your application can request services from applications related to your
- own—for example, asking a spelling checker application to check the text in a
- document created by your application. All publicly available Apple events are
- defined and published in the Apple Event Registry. Consult the Apple Event
- Registry for the format and function of Apple events that your application may
- wish to send.
-
- The previous section describes how a server application responds to a client
- application’s request for services. This section briefly describes the steps
- your application must take to act as a client application and request such
- services. To request a service through an Apple event, your application must
-
- • create an Apple event by calling the AECreateAppleEvent function
-
- • use Apple Event Manager functions to add parameters and any other necessary
- attributes to the Apple event
-
- • call the AESend function to send the Apple event
-
- • dispose of any copies of descriptor records that you have created
-
- • process the reply Apple event (optional)
-
- Use the AECreateAppleEvent function to create an Apple event record. Using the
- arguments you pass to the AECreateAppleEvent function, the Apple Event Manager
- constructs the data structures describing the event class, the event ID, and the
- target address attributes of an Apple event. The event class and event ID, of
- course, identify the particular event you wish to send. The target address
- identifies the application to which you wish to send the Apple event.
-
- To act as a server application for your application, the target must support
- high-level events and must be open. The server can be your own application,
- another application running on the user’s computer, or an application running on
- another user’s computer connected to the network. Your application should offer
- some facility to launch a server application if it is not already running. It is
- recommended that you use the Open Selection event (identified by the event class
- kAEFinderEvents and the event ID kAEOpenSelection) to request that the Finder
- launch applications; however, the Process Manager also provides a means for your
- application to launch other applications. See the Apple Event Registry for
- information on Finder events, and see the Process Management chapter in this
- volume for information on using the Process Manager.
-
- Your application should also offer a facility to allow the user to choose among
- the various applications available as servers. The PPCBrowser function allows
- users to select target applications on the user’s computer as well as those
- available on computers connected to the network. The PPCBrowser function
- presents a standard user interface for choosing a target application, much as
- the Standard File Package provides a standard user interface for opening and
- saving files. See the Program-to-Program Communications Toolbox chapter of this
- volume for details on using the PPCBrowser function.
-
- If the server application is on a remote computer on a network, the user of that
- computer must allow program linking to the server application. The user of the
- server application does this by selecting the application from the Finder and
- choosing Sharing from the File menu and then clicking the Allow Remote Program
- Linking checkbox. If the user has not yet started program linking, the Sharing
- command offers to display the Sharing Setup control panel so that the user can
- start program linking. The user must also authorize remote users for program
- linking by using the Users and Groups control panel. Program linking and setting
- up authenticated sessions are described in the Program-to-Program Communications
- chapter in this volume.
-
- There are two other attributes you specify in the AECreateAppleEvent function:
- the reply ID and the transaction ID. For the reply ID attribute, you’ll usually
- specify the kAutoGenerateReturnID constant to the AECreateAppleEvent function.
- This ensures that the Apple Event Manager generates a unique return ID for the
- reply Apple event returned from the server. For the transaction ID attribute,
- you’ll usually specify the kAnyTransactionID constant, which indicates that this
- Apple event is not one of a series of interdependent Apple events.
-
- The Apple event record created with the AECreateAppleEvent function serves as a
- template for the Apple event you want to send. To add the remaining attributes
- and parameters necessary for your Apple event, you must use these additional
- Apple Event Manager functions.
-
- Function Description
-
- AEPutParamPtr Takes a keyword, descriptor type, and a pointer to
- data,
- converts them into a parameter,
- and adds the parameter
- to or replaces it in an Apple
- event record; used, for
- example, to place numbers into
- the parameters of an
- Apple event requesting that the
- server perform a
- calculation.
-
- AEPutParamDesc Takes a keyword and a descriptor record, converts
- them
- into a parameter, and adds the
- parameter to or replaces it
- in an Apple event record; used,
- for example, to place a
- descriptor list containing alias
- records into the direct
- parameter of an Apple event that
- requests a server to
- manipulate files.
-
- AEPutAttributePtr Takes a keyword, descriptor type, and a pointer to
- data,
- converts them into an attribute,
- and adds the attribute to
- or replaces it in an Apple event
- record; used, for
- example, to change the event ID
- of an Apple event
- record that is waiting to be
- sent.
-
- AEPutAttributeDesc Takes a keyword and a descriptor record, converts
- them
- into an attribute, and adds the
- attribute to or replaces it in
- an Apple event record; used, for
- example, to replace the
- descriptor record used for the
- target address attribute in
- an Apple event record waiting to
- be sent.
-
- Descriptor records and descriptor lists are the basic components from which an
- Apple event record is constructed; these are passed to the AEPutParamDesc and
- AEPutAttributeDesc functions. Use the following functions to create descriptor
- records and descriptor lists.
-
- Function Description
-
- AECreateDesc Takes a descriptor type and a pointer to data
- and converts
- them into a descriptor record;
- used, for example, to create
- a descriptor record that is used
- as an attribute or a
- parameter in an Apple event
- record.
-
- AEPutPtr Takes a descriptor type and a pointer to
- data, converts
- them into a descriptor record,
- and adds the record to a
- descriptor list; used, for
- example, to place into a
- descriptor list a number that is
- used as the parameter of
- an Apple event requesting a
- calculation.
-
- AEPutDesc Adds a descriptor record to a descriptor
- list; used, for
- example, to add into the
- descriptor list an alias record
- that is used as the direct
- parameter of an Apple event
- requesting file manipulation.
-
- After you add all the attributes and parameters required for the Apple event,
- use the AESend function to send the Apple event. The Apple Event Manager uses
- the Event Manager to transmit the Apple event to the server application.
-
- The AESend function requires that you specify whether and how your application
- should wait for a reply from the server. When the server receives your Apple
- event, the Apple Event Manager prepares a reply Apple event for your application
- by passing a default reply Apple event to the server. The Apple Event Manager
- returns any nonzero result code from the server’s handler in the keyErrorNumber
- parameter of the reply Apple event. If your application wants to return an error
- string, add it to the reply Apple event in the keyErrorString parameter. The
- server can also use this reply Apple event to return any data you requested—for
- example, the results of a numerical calculation or a list of misspelled words.
-
- You specify how your application should wait for a reply by using one of these
- flags in the sendMode parameter of the AESend function.
-
- Flag Description
-
- kAENoReply Your application does not want a reply Apple event;
- the
- server processes your Apple event as
- soon as it has the
- opportunity.
-
- kAEQueueReply Your application wants a reply Apple event; the reply
- appears in your event queue as soon
- as the server has the
- opportunity to process and respond to
- your Apple event.
-
- kAEWaitReply Your application wants a reply Apple event and is
- willing to
- give up the processor while waiting
- for the reply; for
- example, if the server application is
- on the same computer
- as your application, your application
- yields the processor to
- allow the server to respond to your
- Apple event.
-
- If you specify the kAEWaitReply flag, you may provide an idle function. This
- function should process any events that occur while your application is waiting
- for a reply. You supply a pointer to your idle function as a parameter to the
- AESend function. So that your application can process other Apple events while
- it is waiting for a reply, you can also specify an optional filter function to
- the AESend function that filters Apple events.
-
- If your Apple event may require the user to interact with the server application
- (for example, to specify print or file options), you can communicate your
- user-interaction preferences to the server by specifying one of the following
- flags in the sendMode parameter of the AESend function.
-
- Flag Description
-
- kAENeverInteract The server application should never interact with the
- user
- in response to this Apple event. If
- this flag is set,
- AEInteractWithUser does not bring the
- server application to
- the foreground (this is the default
- when an Apple event is
- sent to a remote application).
-
- kAECanInteract The server application can interact with the user in
- response
- to this Apple event—by convention, if
- the user needs to
- supply information to the server. If
- this flag is set and the
- server allows interaction,
- AEInteractWithUser brings the
- server application to the foreground
- (this is the default
- when an Apple event is sent to a local
- application).
-
- kAEAlwaysInteract The server application can interact with the user in
- response to this Apple event—by
- convention, even if no
- information is needed from the user.
- If this flag is set and
- the server allows interaction,
- AEInteractWithUser brings
- the server application to the
- foreground. The Apple Event
- Manager does not distinguish between
- this flag and the
- kAECanInteract flag—distinguishing
- between them is the
- responsibility of the server
- application.
-
- kAECanSwitchLayer If both the client and server allow interaction and this
- flag
- is set, AEInteractWithUser brings
- the server directly to the
- foreground if adherence to the
- principle of user control
- allows. If the action would be
- contrary to this principle,
- AEInteractWithUser uses the
- Notification Manager to
- request that user bring the server
- application to the
- foreground. If both the client and
- server allow interaction
- and this flag is not set,
- AEInteractWithUser always uses the
- Notification Manager to request that
- the user bring the
- server application to the
- foreground.
-
- The server can set its own interaction preferences. The interaction of your
- client’s preferences and the server’s is explained in “Interacting With the
- User” later in this chapter.
-
- After you send an Apple event, your application is responsible for disposing of
- the Apple event record—and thereby deallocating the memory it uses—by calling
- the AEDisposeDesc function. If you create one descriptor record and add it to
- another, the Apple Event Manager creates a copy of the newly created one and
- adds that copy to the existing one. For example, you might use the AECreateDesc
- function to create a descriptor record that you wish to add to an Apple event.
- When you use the AEPutParamDesc function, it creates a copy of your newly
- created descriptor record and adds that copy as a parameter to an existing Apple
- event.
-
- Your application should dispose of all the descriptor records that are created
- in order to add parameters and attributes to an Apple event. You normally
- dispose of your Apple event and its reply after you receive a result from the
- AESend function. You should dispose of these even if AESend returns an error
- result. If your application requests a reply Apple event, your application must
- also dispose of the reply Apple event when finished processing it.
-
- Your application can request a reply Apple event. If you specify the
- kAEWaitReply flag, the reply Apple event is returned in a parameter you pass to
- the AESend function. If you specify the kAEQueueReply flag to the AESend
- function, the reply Apple event is returned in the event queue. In this case,
- the reply is identified by the event class kCoreEventClass and the event ID
- kAEAnswer; your application processes reply events that it receives in its event
- queue in the same manner that server applications process Apple events, as
- described earlier in “Responding to Apple Events.”
-
- Your application should check for the keyErrorNumber parameter of the reply
- Apple event to ensure that the server performed the requested action. Any error
- messages that the server returns for you to display to your user will appear in
- the keyErrorString parameter.
-
- When your handler is finished using a copy of a descriptor record used in the
- reply Apple event, you should dispose of them both—and thereby deallocate the
- memory they use—by calling the AEDisposeDesc function.
-
- The next section, “Using the Apple Event Manager,” describes in greater detail
- the routines necessary for sending and responding to Apple events.
-
- _______________________________________________________________________________
-
- æKY Using…the…Apple…Event…Manager…Volume…VI
- æC »Using the Apple Event Manager Volume VI The Apple Event Manager
- _______________________________________________________________________________
-
- The following sections explain in more detail how to use the Apple Event Manager
- to receive, accept, and send Apple events. The first two sections describe how
- to accept and process Apple events and how to install entries into the Apple
- event dispatch table. The following section fully explains how your application
- should handle the required Apple events, and it provides code that shows sample
- handlers for the required Apple events.
-
- Additional sections describe how to
-
- • handle events that support publish and subscribe features
-
- • get data out of an Apple event
-
- • write handlers that perform the action requested by an Apple event
-
- • reply to an Apple event
-
- • dispose of Apple event data structures
-
- • interact with the user when processing an Apple event
-
- • create an Apple event
-
- • send an Apple event
-
- • write an idle function
-
- • write a reply filter function
-
- • write and install coercion handlers
-
- • use the Application Died event to ascertain the termination of an
- application
- that has been launched by your application
-
- The Apple Event Manager is available only in system software version 7.0. Use
- the Gestalt function with the gestaltAppleEventsAttr selector to determine
- whether the Apple Event Manager is available. In the response parameter, the bit
- defined by the constant gestaltAppleEventsPresent is set if the Apple Event
- Manager is available.
-
- CONST gestaltAppleEventsAttr = 'evnt'; {Gestalt selector}
- gestaltAppleEventsPresent = 0; {if this bit is set, then }
- {Apple Event Mgr’s available}
- _______________________________________________________________________________
-
- æKY Accepting…an…Apple…Event
- æC »Accepting an Apple Event The Apple Event Manager
- _______________________________________________________________________________
-
- To accept Apple events (or any other high-level events), you must set the
- appropriate flags in your application’s 'SIZE' resource and include code to
- handle high-level events in your application’s main event loop.
-
- Two flags in the 'SIZE' resource determine whether an application receives
- high-level events:
-
- • The isHighLevelEventAware flag must be set for your application to receive
- any
- high-level events.
-
- • The localAndRemoteHLEvents flag must be set for your application to receive
- high-level events sent from another computer on the network.
-
- Note that in order for your application to respond to Apple events sent from
- remote computers, the user of your application must also allow network users to
- link to your application. The user does this by selecting your application from
- the Finder and choosing Sharing from the File menu and then clicking the Allow
- Remote Program Linking checkbox. If the user has not yet started program
- linking, the Sharing command offers to display the Sharing Setup control panel
- so that the user can start program linking. The user must also authorize remote
- users for program linking by using the Users and Groups control panel. Program
- linking and setting up authenticated sessions are described in the
- Program-to-Program Communications chapter in this volume.
-
- For a complete description of the 'SIZE' resource, see the Event Manager chapter
- in this volume.
-
- Apple events (and other high-level events) are identified by a message class of
- kHighLevelEvent in the what field of the event record. You can test the what
- field of the event record to determine whether the event is a high-level event.
-
- Listing 6-1 is an example of a procedure called from an application’s main event
- loop that handles events, including high-level events. The procedure determines
- the type of event received and then calls another routine to take the
- appropriate action.
-
- ¿ Listing 6-1 A DoEvent procedure
-
- PROCEDURE DoEvent (event: EventRecord);
-
- BEGIN
- CASE event.what OF {determine the type of event}
- mouseDown:
- DoMouseDown (event);
- .
- . {handle other kinds of events}
- .
- {handle high-level events, including Apple events}
- kHighLevelEvent:
- DoHighLevelEvent (event);
- END;
- END;
-
- Listing 6-2 is an example of a DoHighLevelEvent procedure that handles Apple
- events and also handles the high-level event identified by the event class
- mySpecialHLEventClass and the event ID mySpecialHLEventID. Note that, in most
- cases, you should use Apple events to communicate with other applications.
-
- ¿ Listing 6-2 A DoHighLevelEvent procedure for handling Apple events and other
- high-level events
-
- PROCEDURE DoHighLevelEvent (event: EventRecord);
-
- VAR
- myErr : OSErr;
- BEGIN
- IF event.message = LongInt(mySpecialHLEventClass) AND
- event.where = LongInt(mySpecialHLEventID) THEN
- BEGIN
- {it's a high-level event that doesn't use AEIMP}
- myErr := HandleMySpecialHLEvent(event);
- IF myErr <> noErr THEN
- DoError(myErr); {perform the necessary error handling}
- END;
- ELSE {otherwise, assume that the event is an Apple event}
- BEGIN
- myErr := AEProcessAppleEvent(event);
- IF myErr <> noErr THEN
- DoError(myErr);
- END;
- END;
-
- If your application accepts high-level events that do not follow the Apple Event
- Interprocess Messaging Protocol (AEIMP), you must dispatch these high-level
- events before calling AEProcessAppleEvent. To dispatch a high-level event that
- does not follow AEIMP, for each event you should check the event class, the
- event ID, or both to see if the event is one that your application can handle.
-
- After receiving a high-level event (and, if appropriate, checking whether it is
- a type of high-level event other than an Apple event), your application
- typically calls the AEProcessAppleEvent function. The AEProcessAppleEvent
- function determines the type of Apple event received, gets the event buffer that
- contains the parameters and attributes of the Apple event, and calls the
- corresponding Apple event handler routine in your application.
-
- You should provide a handler routine for each Apple event that your application
- supports. Your handler routine for a particular Apple event is responsible for
- performing the action requested by the Apple event, and your handler can
- optionally return data in the reply Apple event.
-
- After your handler finishes processing the Apple event and adds any parameters
- to the default reply, it should return a result code to AEProcessAppleEvent. If
- the client application is waiting for a reply, the Apple Event Manager returns
- the reply Apple event to the client.
-
- _______________________________________________________________________________
-
- æKY Installing…Entries…Into…the…Apple…Event…Dispatch…Tables
- æC »Installing Entries Into the Apple Event Dispatch Tables The Apple Event Manager
- _______________________________________________________________________________
-
- When your application receives an Apple event, use the AEProcessAppleEvent
- function to retrieve the data buffer of the event and to route the Apple event
- to the appropriate Apple event handler in your application. Your application
- supplies an Apple event dispatch table to provide a mapping between the Apple
- events your application supports and the Apple event handlers provided by your
- application.
-
- To install entries into your application’s Apple event dispatch table, use the
- AEInstallEventHandler function. You usually install entries for all of the Apple
- events that your application accepts into your application’s Apple event
- dispatch table.
-
- For each Apple event your application supports, you should install entries in
- your Apple event dispatch table that specify
-
- • the event class of the Apple event
-
- • the event ID of the Apple event
-
- • the address of the Apple event handler for the Apple event
-
- • a reference constant
-
- You provide this information to the AEInstallEventHandler function. In addition,
- you indicate to the AEInstallEventHandler function whether the entry should be
- added to your application’s Apple event dispatch table or the system Apple event
- dispatch table.
-
- The system Apple event dispatch table is a table in the system heap that
- contains handlers that are available to all applications and processes running
- on the same computer. The handlers in your application’s Apple event dispatch
- table are available only to your application. If AEProcessAppleEvent cannot find
- a handler for the Apple event in your application’s Apple event dispatch table,
- it looks in the system Apple event dispatch table for a handler. If it doesn’t
- find a handler there either, it returns the errAEEventNotHandled result code.
-
- Listing 6-3 illustrates how to add entries for the required Apple events to
- your application’s Apple event dispatch table.
-
- ¿ Listing 6-3 Inserting entries for required Apple events into an
- application’s Apple event dispatch table
-
- myErr := AEInstallEventHandler (kCoreEventClass, kAEOpenApplication,
- @MyOAPP, 0, FALSE);
- IF myErr <> noErr THEN DoError(myErr);
- myErr := AEInstallEventHandler (kCoreEventClass, kAEOpenDocuments,
- @MyODOC, 0, FALSE);
- IF myErr <> noErr THEN DoError(myErr);
- myErr := AEInstallEventHandler (kCoreEventClass, kAEPrintDocuments,
- @MyPDOC, 0, FALSE);
- IF myErr <> noErr THEN DoError(myErr);
- myErr := AEInstallEventHandler (kCoreEventClass, kAEQuitApplication,
- @MyQUIT, 0, FALSE);
- IF myErr <> noErr THEN DoError(myErr);
-
- The code in Listing 6-3 creates an entry for all required Apple events in the
- Apple event dispatch table. The first entry creates an entry for the Open
- Application event. The entry indicates the event class and event ID of the Open
- Application event, the address of the handler for that event, and specifies 0 as
- the reference constant. This entry is installed into the application’s Apple
- event dispatch table.
-
- The reference constant is passed to your handler by the Apple Event Manager each
- time your handler is called. Your application can use this reference constant
- for any purpose. If your application doesn’t use the reference constant, use 0
- as the value.
-
- The last parameter to the AEInstallEventHandler function is a Boolean value that
- determines whether the entry is added to the system Apple event dispatch table
- or to your application’s Apple event dispatch table. To add the entry to your
- application’s dispatch table, use FALSE as the value of this parameter. If you
- specify TRUE, the entry is added to the system’s Apple event dispatch table.
-
- If you add a handler to the system Apple event dispatch table, the handler that
- you specify must reside in the system heap.
-
- Note: When an application calls a system Apple event handler, the A5 register
- is
- set up for the calling application. For this reason, if you provide a system
- Apple
- event handler, it should never use A5 global variables or anything that
- depends
- on a particular context; otherwise, the application that calls the system
- handler
- may crash.
-
- For any entry in your Apple event dispatch table, you can specify a wildcard
- value for the event class, event ID, or both. You specify a wildcard by
- supplying the typeWildCard constant when installing an entry into the Apple
- event dispatch table. A wildcard value matches all possible values.
-
- For example, if you specify an entry with the typeWildCard event class and the
- kAEOpenDocuments event ID, the Apple Event Manager dispatches Apple events of
- any event class and an event ID of kAEOpenDocuments to the handler for that
- entry.
-
- If you specify an entry with the kCoreEventClass event class and the
- typeWildCard event ID, the Apple Event Manager dispatches Apple events of the
- kCoreEventClass event class and any event ID to the handler for that entry.
-
- If you specify an entry with the typeWildCard event class and the typeWildCard
- event ID, the Apple Event Manager dispatches all Apple events of any event class
- and any event ID to the handler for that entry.
-
- If the AEProcessAppleEvent function cannot find a handler for an Apple event in
- either the application’s Apple event dispatch table or the system Apple event
- dispatch table, it returns the result code errAEEventNotHandled to the Apple
- event server. If the client is waiting for a reply, AESend also returns this
- result code as its function result.
-
- If your application supports the Edition Manager, you should also add entries to
- your application’s Apple event dispatch table for the Apple events that your
- application receives from the Edition Manager. Listing 6-4 shows how to add
- entries for these Apple events to your application’s Apple event dispatch table.
-
- ¿ Listing 6-4 Inserting entries for Apple events sent by the Edition Manager
- into an application’s Apple event dispatch table
-
- myErr := AEInstallEventHandler(sectionEventMsgClass, sectionReadMsgID,
- @MyHandleSectionReadEvent, 0, FALSE);
- IF myErr <> noErr THEN DoError(myErr);
- myErr := AEInstallEventHandler(sectionEventMsgClass,
- sectionWriteMsgID,
- @MyHandleSectionWriteEvent, 0, FALSE);
- IF myErr <> noErr THEN DoError(myErr);
- myErr := AEInstallEventHandler(sectionEventMsgClass,
- sectionScrollMsgID,
- @MyHandleSectionScrollEvent, 0, FALSE);
- IF myErr <> noErr THEN DoError(myErr);
-
- See “Handling Apple Events Sent by the Edition Manager” later in this chapter
- for the parameters associated with these events. See the Edition Manager chapter
- in this volume for information on how your application should respond to the
- Apple events sent by the Edition Manager.
- _______________________________________________________________________________
-
- æKY Handling…the…Required…Apple…Events
- æC »Handling the Required Apple Events The Apple Event Manager
- _______________________________________________________________________________
-
- This section describes the required Apple events—the Apple events your
- application must support to be 7.0-friendly—and the descriptor types for all
- parameters of the required Apple events. It also describes how to write the
- handlers for these events, and it provides sample code.
-
- To support the required Apple events, you must set the necessary flags in the
- 'SIZE' resource of your application, install entries into your application’s
- Apple event dispatch table, add code to the event loop of your application to
- recognize high-level events, and call the AEProcessAppleEvent function, as
- described in the preceding two sections. You must also write handlers to handle
- each Apple event; this section describes how to write these handlers.
-
- _______________________________________________________________________________
-
- æKY Required…Apple…Events
- æC »Required Apple Events The Apple Event Manager
- _______________________________________________________________________________
-
- When a user opens or prints a file from the Finder, the Finder sets up the
- information your application can use to determine which files to open or print.
- In version 7.0, if your application supports high-level events, the Finder
- communicates this information to your application through the required Apple
- events.
-
- The Finder sends one of the required Apple events to your application to request
- that it open or print a list of documents, inform it that the Finder has just
- opened your application, or inform it that the Finder is about to terminate your
- application.
-
- These are the required Apple events.
-
- Apple event Requested action
-
- Open Application Perform tasks associated with opening your
- application
-
- Open Documents Open the specified documents
-
- Print Documents Print the specified documents
-
- Quit Application Perform tasks—such as releasing memory,
- requesting
- the user to save documents, and
- so on—associated with
- quitting; the Finder sends this
- event to an application
- immediately after sending it a
- Print Documents event or
- if the user chooses Restart or
- Shut Down from the
- Finder’s Special menu.
-
- The Finder uses the required Apple events as part of the new mechanisms in
- system software version 7.0 for launching and terminating applications. This new
- method of communicating Finder information to your application replaces the
- mechanisms used in earlier versions of system software.
-
- Applications that do not support high-level events can still use the
- CountAppFiles, GetAppFiles, and ClrAppFiles procedures (or the GetAppParms
- procedure) to get the Finder information. See the Segment Loader chapter of
- Volume II for information on these routines. To make your application
- 7.0-friendly and compatible with earlier versions of system software, it must
- support both the old and new mechanisms.
-
- Use the Gestalt function to determine whether the Apple Event Manager is
- present. If it is and the isHighLevelEventAware flag is set in your
- application’s 'SIZE' resource, your application receives the Finder information
- through the required Apple events.
-
- If your application accepts high-level events, the Finder sends it an Open
- Application, Open Documents, or Print Documents event immediately after
- launching your application. Upon receiving any of these events, your application
- should perform the action requested by the event.
-
- Note: This section describes the required Apple events as they are sent by
- the
- Finder. When sent by other applications or processes, these same Apple
- events—which are among the core Apple events described in the Apple Event
- Registry—can include optional parameters not listed here. To be 7.0-friendly,
-
- your application only needs to handle the required parameters that are
- described
- in this section.
-
- Open Application—perform tasks associated with opening an application
-
- Event class kCoreEventClass
-
- Event ID kAEOpenApplication
-
- Parameters None
-
- Requested action Perform any tasks—such as opening an untitled document
- window—that you would normally perform
- when a user
- opens your application.
-
- Open Documents—open the specified documents
-
- Event class kCoreEventClass
-
- Event ID kAEOpenDocuments
-
- Required parameter Keyword: keyDirectObject
- Descriptor type: typeAEList
- Data: A list
- of alias records for the documents
- to
- be
-
-
-
- Requested action Open the documents specified in the keyDirectObject
- parameter.
-
- Print Documents—print the specified documents
-
- Event class kCoreEventClass
-
- Event ID kAEPrintDocuments
-
- Required parameter Keyword: keyDirectObject
- Descriptor type: typeAEList
- Data: A list
- of alias records for the documents
- to
-
-
-
- Requested action Print the documents specified in the keyDirectObject
- parameter without opening windows for
- the documents.
- The documents should remain open
- afterward.
-
- Quit Application—perform tasks associated with quitting
-
- Event class kCoreEventClass
-
- Event ID kAEQuitApplication
-
- Parameters None
-
- Requested action Perform any tasks that your application would
- normally
- perform when the user chooses Quit.
- Such tasks typically
- include asking the user if he or she
- wants to save
- documents that have been changed. The
- Finder sends this
- event to an application immediately
- after sending it a Print
- Documents event or if the user chooses
- Restart or Shut
- Down from the Finder’s Special menu.
-
- Your application needs to recognize only two descriptor types to handle the
- required Apple events: descriptor lists and alias records. The Open Documents
- event and Print Documents event use descriptor lists to store a list of
- documents to open. Each document is specified as an alias record in the
- descriptor list.
-
- You can retrieve the data that specifies the document to open as an alias
- record, or you can request that the Apple Event Manager coerce the alias record
- to a file system specification (FSSpec) record. The file system specification
- record provides a standard method of identifying files in version 7.0. See the
- File Manager chapter in this volume for a complete description of how to specify
- files using file system specification records.
- _______________________________________________________________________________
-
- æKY Handling…the…Open…Application…Event
- æC »Handling the Open Application Event The Apple Event Manager
- _______________________________________________________________________________
-
- To handle the Open Application event, your application should do just what it
- does when the user opens your application. For example, your application might
- open a new untitled document window in response to an Open Application event.
-
- Listing 6-5 shows a handler that processes the Open Application event. The Open
- Application event does not have any required parameters. This handler first
- calls an application-defined function called MyGotRequiredParams. This function
- checks whether the Apple event contains any required parameters. By definition,
- the Open Application event should not contain any required parameters so, if the
- Apple event does contain any, the handler returns an error. Otherwise the
- handler opens a new document window.
-
- ¿ Listing 6-5 A handler for the Open Application event
-
- FUNCTION MyHandleOApp (theAppleEvent, reply: AppleEvent;
- handlerRefcon: LongInt) : OSErr;
- VAR
- myErr: OSErr;
- BEGIN
- myErr := MyGotRequiredParams (theAppleEvent);
- IF myErr <> noErr THEN
- MyHandleOApp := myErr
- ELSE
- BEGIN
- DoNew;
- MyHandleOApp := noErr;
- END;
- END;
-
- The MyGotRequiredParams function checks that all required parameters have been
- extracted from the Apple event. See Listing 6-11 in “Writing Apple Event
- Handlers” later in this chapter for a description of the MyGotRequiredParams
- function.
- _______________________________________________________________________________
-
- æKY Handling…the…Open…Documents…Event
- æC »Handling the Open Documents Event The Apple Event Manager
- _______________________________________________________________________________
-
- To handle the Open Documents event, your application should open the documents
- specified in the Apple event. The Open Documents event contains a list of
- documents to open in its direct parameter. Your application extracts this
- information and then opens the specified documents.
-
- Listing 6-6 shows a handler for the Open Documents event. The handler
- illustrates how to open the documents referred to in the direct parameter.
-
- ¿ Listing 6-6 A handler for the Open Documents event
-
- FUNCTION MyHandleODoc (theAppleEvent, reply: AppleEvent;
- handlerRefcon: LongInt) : OSErr;
- VAR
- myFSS: FSSpec;
- docList: AEDescList;
- myErr: OSErr;
- index, itemsInList: LongInt;
- actualSize: Size;
- keywd: AEKeyword;
- returnedType: DescType;
- BEGIN
- {get the direct parameter--a descriptor list--and put it into docList}
- myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList,
- docList);
- IF myErr <> noErr THEN DoError(myErr);
- {check for missing required parameters}
- myErr := MyGotRequiredParams(theAppleEvent);
- IF myErr <> noErr THEN {an error occurred}
- BEGIN {do the necessary error handling}
- MyHandleODoc := myErr;
- Exit (MyHandleODoc);
- END;
- {count the number of descriptor records in the list}
- myErr := AECountItems (docList, itemsInList);
- {now get each descriptor record from the list, get the alias record }
- { out of it, and open the associated file}
- FOR index := 1 TO itemsInList DO
- BEGIN
- myErr := AEGetNthPtr(docList, index, typeFSS, keywd,
- returnedType, @myFSS, Sizeof(myFSS),
- actualSize);
- IF myErr <> noErr THEN DoError(myErr);
- myErr := MyOpenFile(@myFSS);
- IF myErr <> noErr THEN DoError(myErr);
- END;
- myErr := AEDisposeDesc(docList);
- MyHandleODoc := noErr;
- END;
-
- The handler in Listing 6-6 first uses the AEGetParamDesc function to get the
- direct parameter (specified by the keyDirectObject keyword) out of the Apple
- event. The handler requests that AEGetParamDesc return a descriptor list in the
- docList variable. The handler then checks to make sure that it has retrieved all
- of the required parameters by calling the MyGotRequiredParams function (see
- Listing 6-11 for a description of this routine).
-
- Once the handler has retrieved the descriptor list from the Apple event, it uses
- AECountItems to count the number of descriptors in the list. Using the returned
- number as an index, the handler can get the data of each descriptor record in
- the list. This handler requests that the AEGetNthPtr function coerce the data in
- the descriptor record to a file system specification record. The handler can
- then use the file system specification record as a parameter to its own routine
- for opening files.
-
- For more information on the AEGetParamDesc function, see “Getting Data out of
- Parameters” later in this chapter. Also see “Getting Data out of Descriptor
- Lists” for further information on the AEGetNthPtr and AECountItems functions.
-
- After extracting the file system specification record that describes the
- document to open, your application can use this record to open the file. For
- example, in Listing 6-6, the code passes the file system specification record to
- its routine for opening files, the MyOpenFile function.
-
- The MyOpenFile function is designed so that it can be called both in response to
- the Open Documents event and to events generated by the user. For example, when
- the user chooses Open from the File menu, the code that handles the mouse-down
- event uses the StandardGetFile procedure to let the user choose a file; it then
- calls MyOpenFile, passing the file system specification record returned by
- StandardGetFile. By isolating code that performs a requested action from code
- that interacts with the user, you can easily adapt your application to handle
- Apple events that request the same action.
-
- Note that your handler should use the AEDisposeDesc function to dispose of the
- descriptor list when your handler no longer requires the data in it. Your
- handler should also return a result code.
- _______________________________________________________________________________
-
- æKY Handling…the…Print…Documents…Event
- æC »Handling the Print Documents Event The Apple Event Manager
- _______________________________________________________________________________
-
- To handle the Print Documents event, your application should print the documents
- specified in the Apple event. The Print Documents event contains a list of
- documents to print in its direct parameter. Your application extracts this
- information and then prints the specified documents. Your application should not
- open any windows for the documents. Also note that your application should
- remain open after processing the Print Documents event; the Finder sends your
- application a Quit Application event immediately after sending it a Print
- Documents event.
-
- Listing 6-7 shows a handler for the Print Documents event. This handler is
- similar to the handler for the Open Documents event. The code illustrates how to
- print the documents referred to in the direct parameter.
-
- ¿ Listing 6-7 A handler for the Print Documents event
-
- FUNCTION MyHandlePDoc (theAppleEvent, reply: AppleEvent;
- handlerRefcon: LongInt) : OSErr;
- VAR
- myFSS: FSSpec;
- docList: AEDescList;
- myErr: OSErr;
- index, itemsInList: LongInt;
- actualSize: Size;
- keywd: AEKeyword;
- returnedType: DescType;
- BEGIN
- {get the direct parameter--a descriptor list--and put it into docList}
- myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList,
- docList);
- IF myErr <> noErr THEN DoError(myErr);
- {check for missing required parameters}
- myErr := MyGotRequiredParams(theAppleEvent);
- IF myErr <> noErr THEN {an error occurred}
- BEGIN
- {do the necessary error handling}
- MyHandlePDoc := myErr;
- Exit(MyHandlePDoc);
- END;
- {count the number of descriptor records in the list}
- myErr := AECountItems (docList, itemsInList);
- {now get each descriptor record from the list, get the alias record }
- { out of it, and print the associated file}
- FOR index := 1 TO itemsInList DO
- BEGIN
- myErr := AEGetNthPtr(docList, index, typeFSS, keywd, returnedType,
- @myFSS, Sizeof(myFSS), actualSize);
- IF myErr <> noErr THEN DoError(myErr);
- MyPrintFile(@myFSS);
- END;
- myErr := AEDisposeDesc(docList);
- MyHandlePDoc := noErr;
- END;
- _______________________________________________________________________________
-
- æKY Handling…the…Quit…Application…Event
- æC »Handling the Quit Application Event The Apple Event Manager
- _______________________________________________________________________________
-
- To handle the Quit Application event, your application should take any actions
- that are necessary before it is terminated (such as saving any open documents).
- Listing 6-8 shows an example of a handler for the Quit Application event.
-
- The Finder sends your application a Quit Application event immediately after a
- Print Documents event. The Finder also sends your application a Quit Application
- event if the user chooses Restart or Shut Down from the Finder’s Special menu.
-
- ¿ Listing 6-8 A handler for the Quit Application event
-
- FUNCTION MyHandleQuit (theAppleEvent, reply: AppleEvent;
- handlerRefcon: LongInt) : OSErr;
- VAR
- userCanceled : Boolean;
- BEGIN
- {check for missing required parameters}
- myErr := MyGotRequiredParams (theAppleEvent);
- IF myErr <> noErr THEN {an error occurred}
- BEGIN
- {do the necessary error handling}
- MyHandleQuit := myErr;
- Exit (MyHandleQuit);
- END;
- userCanceled := MyPrepareToTerminate;
- IF userCanceled THEN
- MyHandleQuit := userCanceledErr
- ELSE
- MyHandleQuit := noErr;
- END;
-
- The handler in Listing 6-8 calls another function supplied by the application,
- the MyPrepareToTerminate function. This function saves the documents for any
- open windows and returns a Boolean value that indicates whether the Quit request
- was canceled by the user. This is another example of isolating code for
- interacting with the user from the code that performs the requested action.
- Structuring your application in this way allows your application to use the same
- routine when responding to a user event (such as choosing the Quit command from
- the File menu) or to the corresponding Apple event. (For a description of the
- MyGotRequiredParams function, see “Writing Apple Event Handlers” later in this
- chapter.)
-
- Note that your handler must not call the ExitToShell procedure. In Listing 6-8,
- the application calls the ExitToShell procedure only if the handler returns
- noErr as its function result.
- _______________________________________________________________________________
-
- æKY Handling…Apple…Events…Sent…by…the…Edition…Manager
- æC »Handling Apple Events Sent by the Edition Manager The Apple Event Manager
- _______________________________________________________________________________
-
- If your application provides publish and subscribe capabilities, it should
- handle the Apple events sent by the Edition Manager in addition to the required
- Apple events. Your application should also handle the Create Publisher event.
- The Create Publisher event is described in the next section.
-
- The Edition Manager sends your application Apple events to communicate
- information about the publishers and subscribers in your application’s
- documents. Specifically, the Edition Manager uses Apple events to notify your
- application
-
- • when the information in an edition is updated
-
- • when your application needs to write the data from a publisher to an edition
-
- • when your application should locate a particular publisher and scroll the
- document to that location
-
- The Apple events sent by the Edition Manager to your application are the Section
- Read event, Section Write event, and Section Scroll event.
-
- Section Read—read information into the specified section
-
- Event class SectionEventMsgClass
-
- Event ID SectionReadMsgID
-
- Required parameter Keyword: keyDirectObject
- descriptor type: typeSectionH
- Data: A handle
- to the section record of the
-
- whose
-
-
-
-
-
-
-
- Requested action Update the subscriber with the new information from
- the
- edition.
-
- Section Write—write the specified section to an edition
-
- Event class SectionEventMsgClass
-
- Event ID SectionWriteMsgID
-
- Required parameter Keyword: keyDirectObject
- descriptor type: typeSectionH
- Data: A
- handle to the section record of the
-
-
-
- Requested action Write the publisher’s data to its edition.
-
- Section Scroll—scroll the document to the specified section
-
- Event class SectionEventMsgClass
-
- Event ID SectionScrollMsgIDi.SectionScrollMsgID event
- ID 6-;
-
- Required parameter Keyword: keyDirectObject
- descriptor type: typeSectionH
- Data: A
- handle to the section record of the
-
- to
-
-
-
-
- Requested action Scroll the document to the publisher identified by
- the
- specified section record.
-
- See the Edition Manager chapter in this volume for details on how your
- application should respond to these events.
- _______________________________________________________________________________
-
- æKY Handling…the…Create…Publisher…Event
- æC »Handling the Create Publisher Event The Apple Event Manager
- _______________________________________________________________________________
-
- If your application supports publish and subscribe capabilities, it should also
- handle the Create Publisher event.
-
- Create Publisher—create a publisher
-
- Event class kAEMiscStdSuite
-
- Event ID kAECreatePublisher
-
- Required parameter none
-
- Optional parameter Keyword: keyDirectObject
- descriptor type:
- typeObjectSpecifier
- Data: The
- part of the document to publish. If
-
-
-
- is
-
-
-
-
-
-
-
-
- Optional parameter Keyword: keyAEEditionFileLoc
- descriptor type: typeAlias
- Data: An
- alias record that contains the
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Requested action Create a publisher for the specified data using the
- specified
- location for the edition container.
- If the data isn’t specified,
- publish the current selection. If
- the location of the edition
- isn’t specified, use the default
- location.
-
- When your application receives the Create Publisher event, it should create a
- publisher by writing the publisher's data to an edition. The data of the
- publisher, and the location and name of the edition, are defined by the Apple
- event. If the Create Publisher event includes a keyDirectObject parameter, then
- your application should publish the data contained in the parameter. If the
- keyDirectObject parameter is missing, then your application should publish the
- current selection. If the document doesn’t have a current selection, your
- handler for the event should return a non-zero result code.
-
- If the Create Publisher event includes a keyAEEditionFileLoc parameter, then
- your application should use the location and name contained in the parameter as
- the default location and name of the edition. If the keyAEEditionFileLoc
- parameter is missing, then your application should use the default location and
- name your application normally uses to specify the edition container.
-
- Listing 6-9 shows a handler for the Create Publisher event. This handler checks
- for the keyDirectObject parameter and the keyAEEditionFileLoc parameter. If
- either of these are not specified, the handler uses default values. The handler
- uses the DoNewPublisher function, an application-defined function, to create the
- publisher and its edition, create a section record, and update other data
- structures associated with the document. See Listing 4-4 in the Edition Manager
- chapter for an example of the DoNewPublisher function.
-
- Note that the handler uses the AEInteractWithUser function to determine if user
- interaction is allowed. If user interaction is allowed, the handler sets the
- promptForDialog variable to TRUE, indicating that the DoNewPublisher function
- should display the publisher dialog box. If user interaction is not allowed, the
- handler sets the promptForDialog variable to FALSE, and the DoNewPublisher
- function does not prompt the user for the location or name of the edition.
-
- ¿ Listing 6-9 Handler for the Create Publisher event
-
- FUNCTION MyHandleCreatePublisherEvent(theAppleEvent, reply: AppleEvent;
- handlerRefcon: LongInt) : OSErr;
- VAR
- myErr: OSErr;
- returnedType: DescType;
- thePublisherDataDesc: AEDesc;
- actualSize: LongInt;
- promptForDialog: Boolean;
- thisDocument: MyDocumentInfoPtr;
- preview: Handle;
- previewFormat: FormatType;
- defaultLocation: EditionContainerSpec;
-
- BEGIN
- MyGetDocumentPtr(thisDocument);
- myErr := AEGetParamDesc(theAppleEvent, keyDirectObject,
- typeObjectSpecifier, thePublisherDataDesc);
- CASE myErr OF
- errAEDescNotFound:
- BEGIN
- {use the current selection as the publisher }
- { set up info for later when DoNewPublisher displays preview}
- preview := MyGetPreviewForSelection(thisDocument);
- previewFormat := 'TEXT';
- END
- noErr:
- {Use the data in keyDirectObject parameter as the publisher }
- { (which is returned in thePublisherDataDesc variable) }
- { set up info for later when DoNewPublisher displays preview}
- MySetInfoForPreview(thePublisherDataDesc, thisDocument,
- preview, previewFormat);
- OTHERWISE
- DoError(myErr);
- END;
- myErr := AEGetParamPtr(theAppleEvent, keyAEEditionFileLoc,
- typeFSS, returnedType,
- @defaultLocation.theFile,
- SizeOf(FSSpec), actualSize);
- CASE myErr OF
- errAEDescNotFound:
- {use the default location as the edition container}
- myErr := MyGetDefaultEditionSpec(thisDocument,
- defaultLocation);
- noErr:
- BEGIN {The keyAEEditionFileLoc parameter }
- { contained a default location}
- defaultLocation.thePart := kPartsNotUsed;
- defaultLocation.theFileScript := smSystemScript;
- END
- OTHERWISE
- DoError(myErr);
- END;
- myErr := MyGotRequiredParams(theAppleEvent);
- IF myErr <> noErr THEN
- BEGIN
- {handle the error appropriately}
- MyHandleCreatePublisherEvent := myErr;
- END;
- promptForDialog := (AEInteractWithUser(kAEDefaultTimeout, NIL,
- @MyIdleFunction) = noErr);
- myErr := DoNewPublisher(thisDocument, promptForDialog,
- preview, previewFormat, defaultLocation);
- {add keyErrorNumber and keyErrorString parameters if desired}
- MyHandleCreatePublisherEvent := myErr;
- END;
- _______________________________________________________________________________
-
- æKY Getting…Data…out…of…an…Apple…Event
- æC »Getting Data out of an Apple Event The Apple Event Manager
- _______________________________________________________________________________
-
- The Apple Event Manager stores the parameters and attributes of an Apple event
- in a format that is internal to the Apple Event Manager. You use Apple Event
- Manager functions to retrieve the data from an Apple event and return it to your
- application in a format your application can use.
-
- The Apple Event Manager provides functions that retrieve data from parameters
- and attributes. Most of these functions are available in two forms: one that
- returns the desired data in a specified buffer and one that returns a descriptor
- record containing the same data. For example, the AEGetParamPtr function returns
- the data of a specified parameter, and the AEGetParamDesc function returns the
- descriptor record of a specified parameter.
-
- You can also use Apple Event Manager functions to get data out of descriptor
- records, descriptor lists, and AE records. You use similar functions to put data
- into descriptor records, descriptor lists, and AE records.
-
- When your handler receives an Apple event, you’ll typically use the
- AEGetParamPtr, AEGetAttrPtr, AEGetParamDesc, or AEGetAttrDesc function to get
- the data out of the Apple event.
-
- Some Apple Event Manager functions let your application request that the data be
- returned using any descriptor type, even if it is different from the original
- descriptor type. If the original data is of a different descriptor type, the
- Apple Event Manager attempts to coerce the data to the requested descriptor
- type.
-
- For example, the AEGetParamPtr function lets you specify the desired descriptor
- type of the resulting data.
-
- VAR
- theAppleEvent: AppleEvent;
- returnedType: DescType;
- multResult: LongInt;
- actualSize: Size;
- myErr: OSErr;
-
- myErr := AEGetParamPtr(theAppleEvent, keyMultResult, typeLongInteger,
- returnedType, @multResult, SizeOf(multResult),
- actualSize);
-
- In this example, the desired type is specified in the third parameter by the
- typeLongInteger descriptor type. This requests that the Apple Event Manager
- coerce the data to the type defined by this descriptor type (a long integer) if
- it is not already of this type.
-
- To ensure that no coercion is performed and that the descriptor type of the
- result is of the same type as the original, you can specify typeWildCard for the
- desired descriptor type.
-
- The Apple Event Manager returns the descriptor type of the resulting data in the
- fourth parameter. This is useful information when you specify typeWildCard as
- the desired descriptor type; you can determine the descriptor type of the
- resulting data by examining the fourth parameter.
-
- The Apple Event Manager can coerce many different types of data into another.
- For example, the Apple Event Manager can convert alias records to file system
- specification records, integers to Boolean data types, and characters to numeric
- data types, in addition to other data type conversions.
-
- You can also provide your own coercion handlers to coerce other data types. See
- “Writing and Installing Coercion Handlers” later in this chapter for information
- on the coercion provided by the Apple Event Manager and how to provide your own
- coercion handlers.
-
- Parameters are keyword-specified descriptor records. You can use AEGetParamDesc
- to get the descriptor record of a parameter, or you can use AEGetParamPtr to get
- the data out of the descriptor record of a parameter. Attributes are also
- keyword-specified descriptor records, and you can use similar routines to get
- the descriptor record of an attribute or to get the data out of an attribute.
-
- The following sections show examples of how to use the AEGetParamPtr,
- AEGetAttrPtr, AEGetParamDesc, or AEGetAttrDesc function to get the data out of
- an Apple event.
- _______________________________________________________________________________
-
- æKY Getting…Data…out…of…a…Parameter
- æC »Getting Data out of a Parameter The Apple Event Manager
- _______________________________________________________________________________
-
- You can use the AEGetParamPtr or AEGetParamDesc function to get the data out of
- a parameter. Use the AEGetParamPtr function to return the data contained in a
- parameter. Use the AEGetParamDesc function when you need to get the descriptor
- record of a parameter. You often use the AEGetParamDesc function to extract the
- descriptor list from a parameter.
-
- You can also use the AEGetKeyPtr function to return the data contained in a
- parameter. The AEGetKeyPtr function provides an additional feature; you can use
- this function to get data out of an AE record. See “Getting Data and
- Keyword-Specified Descriptor Records From AE Records” later in this chapter for
- information on this function.
-
- For example, you use an Apple Event Manager function to get the data out of a
- Section Read event. The Edition Manager sends your application a Section Read
- event to tell your application to read updated information from an edition into
- the specified subscriber. The direct parameter of the Apple event contains a
- handle to the section record of the subscriber. You can use the AEGetParamPtr
- function to get the data out of the Apple event.
-
- You specify the Apple event that contains the desired parameter, the keyword of
- the desired parameter, the descriptor type the function should use to return the
- data, a buffer to store the data, and the size of this buffer as parameters to
- the AEGetParamPtr function. The AEGetParamPtr function returns the descriptor
- type of the resulting data and the actual size of the data, and it places the
- requested data in the specified buffer.
-
- VAR
- SectionH: sectionHandle;
- theAppleEvent: AppleEvent;
- returnedType: DescType;
- actualSize: Size;
- myErr: OSErr;
-
- myErr := AEGetParamPtr(theAppleEvent, keyDirectObject, typeSectionH,
- returnedType, @sectionH, SizeOf(sectionH),
- actualSize);
-
- In this example, the keyDirectObject keyword specifies that the AEGetParamPtr
- function should extract information from the direct parameter; AEGetParamPtr
- returns the data in the buffer specified by the sectionH variable.
-
- You can request that the Apple Event Manager return the data using the
- descriptor type of the original data or you can request that the Apple Event
- Manager coerce the data into a descriptor type that is different from the
- original. You can specify the desired descriptor type as typeWildCard if you
- don’t want any coercion performed—in which case, the AEGetParamPtr function
- returns the original descriptor type of the parameter.
-
- The typeSectionH descriptor type specifies that the returned data should be
- coerced to a handle to a section record. In this example, the Apple Event
- Manager automatically coerces the data from a temporary ID to a handle to a
- section record when you specify the typeSectionH descriptor type. You can use
- the information returned in the sectionH variable to identify the subscriber and
- read in the information from the edition.
-
- In this example, the AEGetParamPtr function returns in the returnedType variable
- the descriptor type of the resulting data. In most cases, the descriptor type of
- the resulting data matches the requested descriptor type, unless the Apple Event
- Manager wasn’t able to coerce the data to the specified descriptor type. If the
- coercion fails, the Apple Event Manager returns the errAECoercionFail result
- code.
-
- The AEGetParamPtr function returns the actual size of the data in the actualSize
- variable. If the value returned in the actualSize variable is greater than the
- amount your application allocated for the buffer to hold the returned data, your
- application can increase the size of its buffer to this amount, and get the data
- again. You can also choose to use the AEGetParamDesc function when your
- application doesn’t know the size of the data.
-
- You can use the AEGetParamDesc function to return the descriptor record of a
- parameter. This function is useful, for example, when extracting descriptor
- lists from a parameter.
-
- You specify the Apple event that contains the desired parameter, the keyword of
- the desired parameter, the descriptor type the function should use to return the
- descriptor record, and a buffer to store the returned descriptor record as
- parameters to the AEGetParamDesc function. The AEGetParamDesc function returns
- the descriptor record using the specified descriptor type.
-
- For example, the direct parameter of the Open Documents event contains a
- descriptor list that specifies the documents to open. You can use the
- AEGetParamDesc function to get the descriptor list out of the direct parameter.
-
- VAR
- docList: AEDescList;
- theAppleEvent: AppleEvent;
- myErr: OSErr;
-
- myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList,
- docList);
-
- In this example, the Apple event specified by the variable theAppleEvent
- contains the desired parameter. The keyDirectObject keyword specifies that the
- AEGetParamDesc function should get the descriptor record of the direct
- parameter. The typeAEList descriptor type specifies that the descriptor record
- should be returned as a descriptor list. In this example, the AEGetParamDesc
- function returns a descriptor list in the docList variable.
-
- The descriptor list contains a list of descriptor records. To get the descriptor
- records and their data out of a descriptor list, use the AECountItems function
- to find the number of descriptor records in the list, and then make repetitive
- calls to the AEGetNthPtr function to get the data out of each descriptor record.
- See “Getting Data out of a Descriptor List” later in this chapter for more
- information.
-
- Note that the AEGetParamDesc function copies the descriptor record from the
- parameter. When you’re done with a descriptor record that you obtained from
- AEGetParamDesc, you must dispose of it by calling the AEDisposeDesc function.
- _______________________________________________________________________________
-
- æKY Getting…Data…out…of…an…Attribute
- æC »Getting Data out of an Attribute The Apple Event Manager
- _______________________________________________________________________________
-
- You can use the AEGetAttributePtr or AEGetAttributeDesc function to get the data
- out of the attributes of an Apple event.
-
- You can get the data out of an attribute using the AEGetAttributePtr function.
- You specify the Apple event that contains the desired attribute, the keyword of
- the desired attribute, the descriptor type the function should use to return the
- data, a buffer to store the data, and the size of this buffer as parameters to
- the AEGetAttributePtr function. The AEGetAttributePtr function returns the
- descriptor type of the returned data and the actual size of the data, and it
- places the requested data in the specified buffer.
-
- For example, this code gets the data out of the keyEventSourceAttr attribute of
- an Apple event.
-
- VAR
- theAppleEvent: AppleEvent;
- returnedType: DescType;
- sourceOfAE: Integer;
- actualSize: Size;
- myErr: OSErr;
-
- myErr := AEGetAttributePtr(theAppleEvent, keyEventSourceAttr,
- typeShortInteger, returnedType, sourceOfAE,
- SizeOf(sourceOfAE), actualSize);
-
- The keyEventSourceAttr keyword specifies the attribute to get the data from. The
- typeShortInteger descriptor type specifies that the data should be returned as a
- short integer; the returnedType variable contains the actual descriptor type
- that is returned. You also must specify a buffer to hold the returned data, and
- specify the size of this buffer. The AEGetAttributePtr function returns the
- actual size of the data returned in the actualSize variable. You can check this
- value to make sure you got all the data.
-
- As with the AEGetParamPtr function, you can request that AEGetAttributePtr
- return the data using the descriptor type of the original data, or you can
- request that the Apple Event Manager coerce the data into a descriptor type that
- is different from the original.
-
- In this example, the AEGetAttributePtr function returns the requested data in
- the sourceOfAE variable, and you can determine the source of the Apple event by
- examining this value.
-
- The next example shows how to use the AEGetAttributePtr function to get data out
- of the keyMissedKeywordAttr attribute. After your handler extracts all known
- parameters from an Apple event, it should check whether the keyMissedKeywordAttr
- attribute exists. If it does, then your handler did not get all of the required
- parameters.
-
- Note that if AEGetAttributePtr returns the errAEDescNotFound result code, then
- the keyMissedKeywordAttr does not exist—which indicates that your application
- has extracted all of the required parameters. If AEGetAttributePtr returns
- noErr, then the keyMissedKeywordAttr does exist—which indicates that your
- handler did not get all of the required parameters.
-
- myErr := AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr,
- typeWildCard, returnedType, NIL, 0,
- actualSize);
-
- The data in the keyMissedKeywordAttr attribute contains the first required
- parameter, if any, that your handler didn’t retrieve. If you want this data
- returned, specify a buffer to hold the data and specify the size of the buffer.
- Otherwise, as in this example, specify NIL as the buffer and 0 as the size of
- the buffer.
- _______________________________________________________________________________
-
- æKY Getting…Data…out…of…a…Descriptor…List
- æC »Getting Data out of a Descriptor List The Apple Event Manager
- _______________________________________________________________________________
-
- You can use the AECountItems function to count the number of items in a
- descriptor list, and you can use AEGetNthDesc or AEGetNthPtr to get a descriptor
- record or its data out of a descriptor list.
-
- The Open Documents event contains a direct parameter that specifies the list of
- documents to open. The list of documents is contained in a descriptor list.
- After extracting the descriptor list from the parameter, you can determine the
- number of items in the list and then extract each descriptor record from the
- descriptor list. See Figure 6-6 in “Data Structures Within Apple Events” earlier
- in this chapter for a depiction of the Open Documents event.
-
- For example, when your handler receives an Open Documents event, you can use the
- AEGetParamDesc function to return the direct parameter as a descriptor list. You
- can then use AECountItems to return the number of descriptor records in the
- list.
-
- VAR
- theAppleEvent: AppleEvent;
- docList: AEDescList;
- itemsInList: LongInt;
- myErr: OSErr;
-
- myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList,
- docList);
- myErr := AECountItems(docList, itemsInList);
-
- The AEGetParamDesc function returns in the docList variable the descriptor list
- from the direct parameter of the Open Documents event. You specify this list to
- the AECountItems function.
-
- You specify the descriptor list whose items you want to count in the first
- parameter to AECountItems. The Apple Event Manager returns the number of items
- in the list in the second parameter. When extracting the descriptor records from
- a list, you often use the number of items as a loop index. Here’s an example:
-
- FOR index := 1 TO itemsInList DO
- BEGIN
- {for each descriptor record in the list, get its data}
- END;
-
- The format of the descriptor records in a descriptor list is private to the
- Apple Event Manager. You must use the AEGetNthPtr or AEGetNthDesc function to
- extract descriptor records from a descriptor list.
-
- You specify the descriptor list that contains the desired descriptor records and
- an index as parameters to the AEGetNthPtr function. The index represents a
- specific descriptor record in the descriptor list. The AEGetNthPtr returns the
- data from the descriptor record represented by the specified index.
-
- You also specify the descriptor type the function should use to return the data,
- a buffer to store the data, and the size of this buffer. The AEGetNthPtr
- function returns the keyword of the parameter, the descriptor type of the
- returned data, and the actual size of the data, and it places the requested data
- in the specified buffer.
-
- Here’s an example that uses the AEGetNthPtr function to extract an item from the
- descriptor list in the direct parameter of the Open Documents event.
-
- myErr := AEGetNthPtr(docList, index, typeFSS, keywd, returnedType,
- @myFSS, Sizeof(myFSS), actualSize);
-
- The docList variable specifies the descriptor list from the direct parameter of
- the Open Documents event. The index variable specifies the index of the
- descriptor record to extract. You can use the typeFSS descriptor type, as in
- this example, to specify that the data be returned as a file system
- specification record. The Apple Event Manager automatically coerces the original
- data type of the descriptor record from an alias record to a file system
- specification record. The AEGetNthPtr function returns the keyword of the
- parameter in the keywd variable. The function returns in the returnedType
- variable the descriptor type of the resulting data.
-
- You specify a buffer to hold the desired data and the size (in bytes) of the
- buffer as parameters to the AEGetNthPtr function. In this example, the myFSS
- variable specifies the buffer. The function returns the actual size of the data
- in the actualSize variable. If this size is larger than the size of the buffer
- you provided, you know that you didn’t get all of the data for the descriptor
- record.
-
- Listing 6-10 shows a more complete example of extracting the items from a
- descriptor list in the Open Documents event.
-
- ¿ Listing 6-10 Extracting items from a descriptor list
-
- VAR
- index: LongInt;
- itemsInList: LongInt;
- docList: AEDescList;
- keywd: AEKeyword;
- returnedType: DescType;
- myFSS: FSSpec;
- actualSize: Size;
- myErr: OSErr;
-
- FOR index := 1 TO itemsInList DO
- BEGIN
- myErr := AEGetNthPtr(docList, index, typeFSS, keywd, returnedType ,
- @myFSS, Sizeof(myFSS), actualSize);
- IF myErr <> noErr THEN DoError(myErr);
- myErr := MyOpenFile(@myFSS);
- IF myErr <> noErr THEN DoError(myErr);
- END;
- myErr := AEDisposeDesc(docList);
- _______________________________________________________________________________
-
- æKY Writing…Apple…Event…Handlers
- æC »Writing Apple Event Handlers The Apple Event Manager
- _______________________________________________________________________________
-
- For each Apple event your application supports, you must provide a function
- called an Apple event handler. The AEProcessAppleEvent function calls one of
- your Apple event handlers when it processes an Apple event. Your Apple event
- handlers should perform any action requested by the Apple event, add parameters
- to the reply Apple event if appropriate, and return a result code.
-
- The Apple Event Manager uses dispatch tables to route Apple events to the
- appropriate Apple event handler. You must supply an Apple event handler for each
- entry in your application’s Apple event dispatch table. Each handler must be a
- function that uses this syntax:
-
- FUNCTION MyEventHandler (theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefcon: LongInt) : OSErr;
-
- The parameter theAppleEvent is the Apple event to handle. Your handler uses
- Apple Event Manager functions to extract any parameters and attributes from the
- Apple event and then performs the necessary processing. The reply parameter is
- the default reply provided by the Apple Event Manager. (“Replying to an Apple
- Event,” later in this chapter, describes how to add parameters to the default
- reply.) The handlerRefcon parameter is the reference constant stored in the
- Apple event dispatch table entry for the Apple event. Your handler can ignore
- this parameter if your application does not use the reference constant.
-
- After extracting all known parameters from the Apple event, every handler should
- determine whether the Apple event contains any further required parameters. Your
- handler can check that it retrieved all the required parameters by checking
- whether the keyMissedKeywordAttr attribute exists. If the attribute exists, then
- your handler has not retrieved all the required parameters. If additional
- required parameters exist, then your handler should immediately return an error.
- If the attribute does not exist, then the Apple event does not contain any more
- required parameters.
-
- Listing 6-11 shows a function that checks for a keyMissedKeywordAttr attribute.
- A handler calls this function after getting all the required parameters it knows
- about from an Apple event.
-
- ¿ Listing 6-11 A function that checks for a keyMissedKeywordAttr attribute
-
- FUNCTION MyGotRequiredParams (theAppleEvent: AppleEvent) : OSErr;
- VAR
- returnedType: DescType;
- actualSize: Size;
- myErr: OSErr;
- BEGIN
- myErr := AEGetAttributePtr (theAppleEvent, keyMissedKeywordAttr,
- typeWildCard, returnedType, NIL, 0,
- actualSize);
- IF myErr = errAEDescNotFound THEN {you got all the required }
- { parameters}
- MyGotRequiredParams := noErr
- ELSE IF myErr = noErr THEN {you missed a required parameter}
- MyGotRequiredParams := errAEEventNotHandled
- ELSE {the call to AEGetAttributePtr failed}
- MyGotRequiredParams := myErr;
- END;
-
- The code in Listing 6-11 uses the AEGetAttributePtr function to get the
- keyMissedKeywordAttr attribute. This attribute contains the first required
- parameter, if any, that your handler didn’t retrieve. If AEGetAttributePtr
- returns the errAEDescNotFound result code, the Apple event doesn’t contain a
- keyMissedKeywordAttr attribute. If the Apple event doesn’t contain this
- attribute, then your handler has extracted all of the required parameters.
-
- If the AEGetAttributePtr function returns noErr as the result code, then the
- attribute does exist, meaning that your handler has not extracted all of the
- required parameters. In this case, your handler should return an error and not
- process the Apple event.
-
- The first remaining required parameter is specified by the data of the
- keyMissedKeywordAttr attribute. If you want this data returned, specify a buffer
- to hold the data. Otherwise, specify NIL as the buffer and 0 as the size of the
- buffer. If you specify a buffer to hold the data, you can check the value of the
- actualSize parameter to see if the data is larger than the buffer you allocated.
- _______________________________________________________________________________
-
- æKY Replying…to…an…Apple…Event
- æC »Replying to an Apple Event The Apple Event Manager
- _______________________________________________________________________________
-
- Your handler routine for a particular Apple event is responsible for performing
- the action requested by the Apple event, and can optionally return data in a
- reply Apple event. The Apple Event Manager passes a default reply Apple event to
- your handler. The default reply Apple event has no parameters when it is passed
- to your handler. Your handler can add parameters to the reply Apple event. If
- the client application requested a reply, the Apple Event Manager returns the
- reply Apple event to the client.
-
- The reply Apple event is identified by the kCoreEventClass event class and by
- the kAEAnswer event ID.
-
- When your handler finishes processing an Apple event, it returns a result code
- to AEProcessAppleEvent. The AEProcessAppleEvent function returns this result
- code as its function result. If your handler returns a nonzero result code, the
- Apple Event Manager also returns this result code to the client application by
- putting the result code into a keyErrorNumber parameter for the reply Apple
- event. The client can check for the existence of this parameter to determine
- whether the handler performed the requested action.
-
- The client application specifies whether it wants a reply Apple event or not by
- specifying flags (represented by constants) in the sendMode parameter of the
- AESend function.
-
- If the client specifies the kAEWaitReply flag in the sendMode parameter, the
- AESend function does not return until the timeout expires or the server returns
- a reply. When the server returns a reply, the reply parameter to AESend contains
- the reply Apple event that your handler returned to the AEProcessAppleEvent
- function.
-
- If the client specified the kAEQueueReply flag, the client receives the reply
- event in its normal processing of other events.
-
- If the client specified the kAENoReply flag, your handler may return a reply
- Apple event to AEProcessAppleEvent, but this reply is not returned to the
- client.
-
- Your handler routine should always set its function result to noErr if it
- successfully handles the Apple event or to a nonzero result code if an error
- occurs. The Apple Event Manager automatically adds any nonzero result code that
- your handler returns to a keyErrorNumber parameter in the reply Apple event. In
- addition to returning a result code, your handler can also return an error
- string in the keyErrorString parameter of the reply Apple event. Your handler
- should provide meaningful text in the keyErrorString parameter, so that the
- client can display this string to the user if desired.
-
- Listing 6-12 shows how to add the keyErrorString parameter to the reply Apple
- event. See “Adding Parameters to an Apple Event” later in this chapter for a
- description of the AEPutParamPtr function.
-
- ¿ Listing 6-12 Adding the keyErrorString parameter to the reply Apple event
-
- FUNCTION MyHandler (theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefcon: LongInt) : OSErr;
- VAR
- myErr: OSErr;
- errStr: Str255;
- BEGIN
- {if an error occurs when handling an Apple event, set the }
- { function result and error string accordingly}
- IF myErr <> noErr THEN
- BEGIN
- MyHandler := myErr; {result code to be returned - the Apple Event }
- { Manager adds this result code to the reply }
- { Apple event as the keyErrorNumber parameter}
- {add error string parameter to the default reply}
- errStr := 'Reason why error occurred';
- myErr := AEPutParamPtr(reply, keyErrorString, typeChar,
- Ptr(@errStr[1]), length(errStr));
- Exit(MyHandler);
- END;
- END;
-
- If your handler needs to return data to the client, it can add parameters to the
- reply Apple event. For example, Listing 6-13 shows how a handler for the
- Multiply event (an imaginary Apple event that asks the server to multiply two
- numbers) might return the results of the multiplication to the client.
-
- ¿ Listing 6-13 Adding parameters to the reply Apple event
-
- FUNCTION MyMultHandler (theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefcon: LongInt) : OSErr;
- VAR
- myErr: OSErr;
- number1, number2: LongInt;
- replyResult: LongInt;
- actualSize: Size;
- returnedType: DescType;
- BEGIN
- {get the numbers to multiply from the parameters of the Apple event }
- { put the numbers in the number1 and number2 variables }
- { then perform the requested multiplication}
- myErr := MyDoMultiply(theAppleEvent, number1, number2, replyResult);
-
- {return the result of the multiplication in the reply Apple event}
- IF myErr = noErr THEN
- BEGIN
- myErr := AEPutParamPtr(reply, keyDirectObject, typeLongInteger,
- @replyResult, SizeOf(replyResult));
- MyMultHandler := myErr;
- END;
- {if an error occurs, set the function result and error string }
- { accordingly, as shown in Listing 6-12}
- END;
- _______________________________________________________________________________
-
- æKY Disposing…of…Apple…Event…Data…Structures
- æC »Disposing of Apple Event Data Structures The Apple Event Manager
- _______________________________________________________________________________
-
- Whenever you use Apple Event Manager functions to create a descriptor record,
- descriptor list, or Apple event record, the Apple Event Manager allocates memory
- for these data structures. Likewise, when you extract a descriptor record by
- using Apple Event Manager functions, the Apple Event Manager creates a copy of
- the descriptor record for you to use.
-
- Whenever you are done using a descriptor record or descriptor list that you have
- created or extracted from an Apple event, you must dispose of the descriptor
- record—and thereby deallocate the memory it uses—by calling the AEDisposeDesc
- function.
-
- Also, when you are done using the Apple event specified in the AESend function
- and finished with the reply Apple event, you should dispose of their descriptor
- records using the AEDisposeDesc function. You should dispose of them even if
- AESend returns a nonzero result code.
-
- Once you are done using them, you should dispose of any Apple event data
- structures created or returned by these functions:
-
- AECreateAppleEvent AECreateList
- AEGetNthDesc AECreateDesc
- AEGetKeyDesc AEGetParamDesc
- AECoerceDesc AEGetAttributeDesc
- AECoercePtr AEDuplicateDesc
- AEGetKeyDesc
-
- Even if you add a descriptor record to an Apple event (for example, when you
- create a descriptor record by calling AECreateDesc and then put a copy of it
- into a parameter of an Apple event by calling AEPutParamDesc), you’re still
- responsible for disposing of the original descriptor record.
-
- In one case, the Apple Event Manager does take care of disposing of the Apple
- event data structures for you: when your handler returns to AEProcessAppleEvent,
- the Apple Event Manager disposes of the Apple event and the reply Apple event.
- Note that your handler is still responsible for disposing of any Apple event
- data structures created when extracting data from the Apple event. The Apple
- event and reply Apple event that your handler receives are only copies of the
- originals. The client application is responsible for disposing of the original
- data structures.
- _______________________________________________________________________________
-
- æKY Interacting…With…the…User
- æC »Interacting With the User The Apple Event Manager
- _______________________________________________________________________________
-
- When your application receives an Apple event, it may need to interact with the
- user. For example, your application may need to display a dialog box asking for
- additional input or confirmation from the user. You must make sure that your
- application is in the foreground before interacting with the user. To do this,
- use the AEInteractWithUser function before actually interacting with the user.
- The AEInteractWithUser function checks the user interaction preferences set by
- the client application and the server application and, if user interaction is
- allowed, brings your application to the front (either directly or by posting a
- notification request) if it is not already in the front.
-
- If both the client and server applications allow user interaction,
- AEInteractWithUser usually posts a notification request; AEInteractWithUser
- brings the server to the front after the user responds to the notification
- request. The AEInteractWithUser function can also bring the server application
- directly to the front—but only when doing so is in accordance with the principle
- of user control and if the client allows it.
-
- Both the client and server specify their preferences for user interaction: the
- client specifies whether the server should be allowed to interact with the user,
- and the server specifies when it will allow user interaction while processing an
- Apple event.
-
- An application that sends an Apple event indicates its preferences for how the
- server application should interact with the user by setting various flags in the
- sendMode parameter to AESend. The Apple Event Manager translates these flags
- into the corresponding flags in the keyInteractLevelAttr attribute of the Apple
- event, and sets them.
-
- The server application sets its preferences by using the AESetInteractionAllowed
- function. This function lets your application specify whether it allows
- interaction with the user as a result of receiving an Apple event from itself;
- from itself and other processes on the local machine; or from itself, local
- processes, and processes from another computer on the network.
-
- Your application calls the AEInteractWithUser function before interacting with
- the user. If AEInteractWithUser returns the noErr result code, then your
- application is currently in the front and your application is free to interact
- with the user. If AEInteractWithUser returns the errAENoUserInteraction result
- code, then the conditions didn’t allow user interaction and your application
- should not interact with the user.
-
- The client application sets user interaction preferences by setting flags in the
- sendMode parameter to the AESend function. The Apple Event Manager automatically
- adds the specified flags to the keyInteractLevelAttr attribute of the Apple
- event. These flags are represented by constants and are described here.
-
- Flag Description
-
- kAENeverInteract The server application should never interact with
- the
- user in response to this Apple
- event. If this flag is set,
- AEInteractWithUser does not bring
- the server application
- to the foreground (this is the
- default when an Apple
- event is sent to a remote
- application).
-
- kAECanInteract The server application can interact with the user
- in
- response to this Apple event—by
- convention, if the user
- needs to supply information to
- the server. If this flag is
- set and the server allows
- interaction,
- AEInteractWithUser brings the
- server application to the
- foreground (this is the default
- when an Apple event is
- sent to a local application).
-
- kAEAlwaysInteract The server application can interact with the user in
-
- response to this Apple event—by
- convention, even if no
- information is needed from the
- user. If this flag is set and
- the server allows interaction,
- AEInteractWithUser brings
- the server application to the
- foreground. The Apple
- Event Manager does not
- distinguish between this flag and
- the kAECanInteract
- flag—distinguishing between them
- is
- the responsibility of the server
- application.
-
- If the client application doesn’t specify any of the user interface flags, the
- Apple Event Manager sets either the kAENeverInteract or the kAECanInteract flag
- in the keyInteractLevelAttr attribute of the Apple event, depending on the
- location of the server application. If the server application is on a remote
- computer, the Apple Event Manager sets the kAENeverInteract flag as the default.
- If the server application is on the local computer, the Apple Event Manager sets
- the kAECanInteract flag as the default.
-
- In addition, the client application can set another flag in the sendMode
- parameter to AESend to request that the Apple Event Manager immediately bring
- the server application to the front (instead of posting a notification
- request)—if user interaction is allowed and if the user interface guidelines
- permit.
-
- Flag Description
-
- kAECanSwitchLayer If both the client and server allow interaction and
- this
- flag is set, AEInteractWithUser
- brings the server directly
- to the foreground if adherence
- to the principle of user
- control allows. If the action
- would be contrary to this
- principle, AEInteractWithUser
- uses the Notification
- Manager to request that user
- bring the server application
- to the foreground. If both the
- client and server allow
- interaction and this flag is not
- set, AEInteractWithUser
- always uses the Notification
- Manager to request that the
- user bring the server
- application to the foreground.
-
- When a server application calls AEInteractWithUser, the function first checks to
- see if the kAENeverInteract flag in the keyInteractLevelAttr attribute of the
- Apple event is set. (The Apple Event Manager sets this attribute according to
- the flags specified in the sendMode parameter of AESend.) If the
- kAENeverInteract flag is set, AEInteractWithUser immediately returns the
- errAENoUserInteraction result code. If the client specified kAECanInteract or
- kAEAlwaysInteract, AEInteractWithUser checks the server’s preferences for user
- interaction.
-
- The server sets its user interaction preferences by using the
- AESetInteractionAllowed function. You use this function to tell the Apple Event
- Manager the processes for which your application is willing to interact with the
- user.
-
- myErr := AESetInteractionAllowed(level);
-
- The level parameter is of type AEInteractAllowed.
-
- TYPE AEInteractAllowed = (kAEInteractWithSelf, kAEInteractWithLocal,
- kAEInteractWithAll);
-
- You can specify one of these values for the interaction level.
-
- Flag Description
-
- kAEInteractWithSelf User interaction with your server application in
- response to an Apple event may
- be allowed only when
- the client application is your
- own application—that is,
- only when your application is
- sending the Apple event
- to itself.
-
- kAEInteractWithLocal User interaction with your server application in
- response to an Apple event may
- be allowed only if the
- client application is on the
- same computer as your
- application; this is the
- default if the
- AESetInteractionAllowed
- function is not used.
-
- kAEInteractWithAll User interaction with your server application in
- response
- to an Apple event may be allowed
- for any client
- application on any computer.
-
- If the server application does not set the user interaction level,
- AEInteractWithUser uses kAEInteractWithLocal as the value.
-
- If the application sent itself an Apple event (that is, the application is both
- the client and the server), AEInteractWithUser always allows user interaction.
- If the client application is a process on the local machine, and the server set
- the interaction level to the kAEInteractWithLocal or kAEInteractWithAll flag,
- then AEInteractWithUser allows user interaction. If the client is a process on a
- remote computer on the network, AEInteractWithUser allows user interaction only
- if the server specified the kAEInteractWithAll flag for the interaction level.
- In all other cases, AEInteractWithUser does not allow user interaction.
-
- When AEInteractWithUser allows user interaction (based on the client and
- server’s preferences), AEInteractWithUser brings the server application to the
- front—either directly or after the user responds to a notification request—and
- then returns a noErr result code.
-
- If AEInteractWithUser cannot bring the server application to the front within
- the specified timeout value, AEInteractWithUser returns the errAETimeout result
- code.
-
- Your application may want to provide the user with a method of setting the
- interaction level. For example, some users may not want to be interrupted while
- background processing of an Apple event occurs, or they may not want to respond
- to dialog boxes when your application is handling Apple events sent from another
- computer.
-
- Listing 6-14 illustrates the use of the AEInteractWithUser function. You call
- this function before your application displays a dialog box or otherwise
- interacts with the user when processing an Apple event. You specify a timeout
- value, a pointer to a Notification Manager record, and the address of an idle
- function as parameters to AEInteractWithUser.
-
- ¿ Listing 6-14 Using the AEInteractWithUser function
-
- myErr := AEInteractWithUser (kAEDefaultTimeOut, NIL, @MyIdleFunction);
- IF myErr <> noErr THEN
- {the attempt to interact failed, do any error handling}
- DoError(myErr)
- ELSE
- {interact with the user by displaying a dialog box }
- { or by interacting in any other way that is necessary}
-
- You can set a timeout value, in ticks, in the first parameter to
- AEInteractWithUser. Use the kAEDefaultTimeout constant if you want the Apple
- Event Manager to use a default value for the timeout value. The Apple Event
- Manager uses a timeout value of about one minute if you specify this constant.
- You can also specify the kNoTimeOut constant if your application is willing to
- wait an indefinite amount of time for a response from the user. Usually you
- should provide a timeout value, so that your application can complete processing
- of the Apple event in a reasonable amount of time.
-
- You can provide a pointer to a Notification Manager record in the second
- parameter, or you can specify NIL to use the default record provided by
- AEInteractWithUser. The AEInteractWithUser function only uses a Notification
- Manager record when user interaction is allowed and the kAECanSwitchLayer flag
- in the keyInteractLevelAttr attribute is not set.
-
- The last parameter to AEInteractWithUser specifies an idle function provided by
- your application. Your idle function should handle any update events, null
- events, operating-system events, or activate events while your application is
- waiting to be brought to the front. See “Writing an Idle Function” later in this
- chapter for more information.
- _______________________________________________________________________________
-
- æKY Creating…an…Apple…Event
- æC »Creating an Apple Event The Apple Event Manager
- _______________________________________________________________________________
-
- You create an Apple event by using the AECreateAppleEvent function. You specify
- the event class and event ID, the target address, the return ID, and the
- transaction ID to the function. The AECreateAppleEvent function creates and
- returns an Apple event with the attributes set as your application requested.
- You should not directly manipulate the contents of the Apple event; rather, use
- Apple Event Manager functions to add additional attributes or parameters to it.
-
- This example creates a Multiply event using the AECreateAppleEvent function. You
- specify the event class, the event ID, the address of the server application, a
- return ID, a transaction ID, and a buffer to store the returned Apple event as
- parameters to AECreateAppleEvent.
-
- myErr := AECreateAppleEvent(kArithmeticClass, kMultEventID,
- targetAddress, kAutoGenerateReturnID,
- kAnyTransactionID,theAppleEvent);
-
- The event class here is identified by the kArithmeticClass constant and
- specifies that this event belongs to a specific class of Apple events for
- arithmetic operations. The event ID specifies the particular Apple event within
- the class; in this case, an Apple event to perform multiplication.
-
- You specify the target of the Apple event in the third parameter to
- AECreateAppleEvent. The target address can identify an application on the local
- computer or another computer on the network. You can specify the address using a
- target ID record or session ID. For processes on the local computer, you can
- also use a process serial number or application signature to specify the
- address. See “Specifying a Target Address” later in this chapter for more
- information.
-
- You specify the return ID of the Apple event in the fourth parameter. The return
- ID provides a way to associate this Apple event to the server’s reply. The
- AECreateAppleEvent function assigns the specified return ID value to the
- keyReturnIDAttr attribute of the Apple event. If a server returns an Apple event
- in response to this event, the server should use the same return ID. When you
- receive an Apple event, you can check the keyReturnIDAttr attribute to determine
- whether the event is a response to an outstanding Apple event. You can use the
- kAutoGenerateReturnID constant to request that the Apple Event Manager generate
- a return ID that is unique to this session for the Apple event.
-
- The fifth parameter specifies the transaction ID attribute of the Apple event. A
- transaction refers to a sequence of Apple events that are sent back and forth
- between the client and server applications, beginning with the client’s initial
- request for a service. All Apple events that are part of one transaction must
- have the same transaction ID.
-
- You can use a transaction ID to indicate that an Apple event is one of a
- sequence of Apple events related to a single transaction. The kAnyTransactionID
- constant indicates that the Apple event is not part of a transaction.
-
- The AECreateAppleEvent function creates an Apple event with only the specified
- attributes and no parameters. To add parameters or additional attributes, use
- other Apple Event Manager functions.
- _______________________________________________________________________________
-
- æKY Adding…Parameters…to…an…Apple…Event
- æC »Adding Parameters to an Apple Event The Apple Event Manager
- _______________________________________________________________________________
-
- You can use the AEPutParamPtr or AEPutParamDesc functions to add parameters to
- an Apple event. When you use either of these functions, the Apple Event Manager
- adds the specified parameter to the Apple event.
-
- Use the AEPutParamPtr function when you want to add data specified in a buffer
- as the parameter of an Apple event. You specify the Apple event, the keyword of
- the parameter to add, the descriptor type, a buffer that contains the data, and
- the size of this buffer as parameters to the AEPutParamPtr function. The
- AEPutParamPtr function creates the descriptor record and adds the parameter to
- the Apple event.
-
- For example, this code adds a parameter to the Multiply event using the
- AEPutParamPtr function.
-
- CONST keyOperand1 = 'OPN1';
- VAR
- number1: Integer;
- theAppleEvent: AppleEvent;
-
- number1 := 10;
- myErr := AEPutParamPtr(theAppleEvent, keyOperand1, typeInteger,
- @number1, SizeOf(number1));
-
- In this example, the Apple Event Manager adds the parameter containing the first
- number to the specified Apple event.
-
- Use the AEPutParamDesc function to add data specified in a descriptor record to
- an Apple event. The descriptor record you specify must have been previously
- created using the AECreateDesc or AEDuplicateDesc function.
-
- You specify the descriptor type, a buffer that contains the data, and the size
- of this buffer as parameters to the AECreateDesc function. The AECreateDesc
- function returns the descriptor record that describes the data.
-
- This example creates a descriptor record for the second parameter of the
- Multiply event:
-
- VAR
- number2: Integer;
- multParam2Desc: AEDesc;
-
- number2 := 8;
- myErr := AECreateDesc(typeInteger, @number2, SizeOf(number2),
- multParam2Desc);
-
- In this example, the AECreateDesc function creates a descriptor record with the
- typeInteger descriptor type and the data identified in the number2 variable.
-
- Once you have created a descriptor record, you can use AEPutParamDesc to add the
- data to a parameter of an Apple event. You specify the Apple event to add the
- parameter to, the keyword of the parameter, and the descriptor record of the
- parameter as parameters to the AEPutParamDesc function.
-
- This example adds a second parameter to the Multiply event using the
- AEPutParamDesc function.
-
- CONST keyOperand2 = 'OPN2';
-
- myErr := AEPutParamDesc(theAppleEvent, keyOperand2, multParam2Desc);
-
- This example adds the keyOperand2 keyword and the descriptor record created in
- the previous example as the second parameter to the specified Apple event.
-
- The previous examples showed how to add parameters to the imaginary Multiply
- event. After adding parameters to an Apple event, you can send the Apple event
- using the AESend function. See “Sending an Apple Event” later in this chapter
- for information on using this function.
- _______________________________________________________________________________
-
- æKY Specifying…a…Target…Address
- æC »Specifying a Target Address The Apple Event Manager
- _______________________________________________________________________________
-
- When you create an Apple event, you must specify the address of the target. The
- target address identifies the particular application or process that you want to
- send the Apple event to. You can send Apple events to applications on the local
- machine or on remote computers on the network.
-
- These are the descriptor types that identify the four methods of addressing an
- Apple event.
-
- typeApplSignature The application signature of the target
-
- typeSessionID The session ID of the target
-
- typeTargetID The target ID record of the target
-
- typeProcessSerialNumber The process serial number of the target
-
- To address an Apple event to a target on a remote computer on the network, you
- must use either the typeSessionID or typeTargetID descriptor type.
-
- If your application sends an Apple event to itself, it should address the Apple
- event using a process serial number. Use the kCurrentProcess constant to specify
- the process serial number of your application. This is the fastest way for your
- application to send an Apple event to itself.
-
- You can use any of the four address types when sending an Apple event to another
- application on the local computer. To allow the user to choose the target of an
- Apple event, use the PPCBrowser function. The PPCBrowser function presents a
- standard user interface for choosing a target application, much as the Standard
- File Package provides a standard user interface for opening and saving files.
-
- The PPCBrowser function returns information about the application the user chose
- in a targetID record. (Listing 6-16 later in this section shows how to use the
- PPCBrowser function to let the user choose a target.)
-
- The Event Manager chapter in this volume describes all four types of addresses.
- Your application can also use another address type, if it also provides a
- coercion handler that coerces the address type into one of the four address
- types that the Apple Event Manager recognizes. See “Writing and Installing
- Coercion Handlers” later in this chapter for more information.
-
- You specify the address using an address descriptor record (a descriptor record
- of data type AEAddressDesc). You must create a descriptor record of this type
- and then supply the address descriptor record as a parameter to the
- AECreateAppleEvent function.
-
- You can use the AECreateDesc function to add any of the four target addresses to
- an address descriptor record. Listing 6-15 shows four possible ways to create an
- address, each using a different address type.
-
- ¿ Listing 6-15 Creating a target address
-
- PROCEDURE SetTargetAddresses(VAR targetAddress1, targetAddress2,
- targetAddress3, targetAddress4:
- AEAdressDesc; toTargetID: TargetID;
- thePSN: ProcessSerialNumber;
- theSignature: OSType;
- theSessionID: sessionID);
- VAR
- myErr: OSErr;
-
- BEGIN
- myErr := AECreateDesc(typeTargetID, @toTargetID, SizeOf(toTargetID),
- targetAddress1);
- myErr := AECreateDesc(typeProcessSerialNumber, @thePSN, SizeOf(thePSN),
- targetAddress2);
- myErr := AECreateDesc(typeApplSignature, @theSignature,
- SizeOf(theSignature), targetAddress3);
- myErr := AECreateDesc(typeSessionID, @theSessionID, SizeOf(theSessionID),
- targetAddress4);
- END;
-
- You specify the descriptor type for the address, a pointer to the buffer
- containing the address, and the size of the buffer to the AECreateDesc function
- to create an address descriptor record. The AECreateDesc function returns an
- address descriptor record with the specified characteristics.
-
- After creating an address, you can specify the address in the AECreateAppleEvent
- function. See “Creating an Apple Event” earlier in this chapter for an example
- using the AECreateAppleEvent function.
-
- When you specify an address to the AECreateAppleEvent function, the Apple Event
- Manager stores the address in the keyAddressAttr attribute of the Apple event.
-
- You can use the PPCBrowser function to create a target ID. Listing 6-16 shows
- how to use the information returned from the PPCBrowser function to create a
- target ID. You can then use AECreateDesc to create the address descriptor record
- for an Apple event.
-
- ¿ Listing 6-16 Specifying a target address in an Apple event
-
- FUNCTION GetTargetAddress(myPrompt: Str255; myAppStr: Str255;
- VAR myPortInfo: PortInfoRec;
- VAR targetAddress: AEAddressDesc;
- VAR toTargetID: targetID) : OSErr;
-
- BEGIN {use PPCBrowser to let user choose the target}
- myErr := PPCBrowser(myPrompt, myAppStr, FALSE, toTargetID.location,
- myPortInfo, NIL, '');
- IF myErr <> noErr THEN
- DoError(myErr);
- ELSE
- BEGIN
- toTargetID.name := myPortInfo.name;
- {create the descriptor record for the target address}
- myErr := AECreateDesc(typeTargetID, @toTargetID,
- SizeOf(toTargetID), targetAddress);
- IF myErr <> noErr THEN
- DoError(myErr);
- END;
- GetTargetAddress := myErr;
- END;
-
- See the Program-to-Program Communications Toolbox chapter for more information
- on using the PPCBrowser function.
- _______________________________________________________________________________
-
- æKY Sending…an…Apple…Event
- æC »Sending an Apple Event The Apple Event Manager
- _______________________________________________________________________________
-
- To send an Apple event, you first create an Apple event, add parameters and
- attributes to the Apple event, and then use the AESend function to send it.
-
- When you send an Apple event, you specify various options to indicate how the
- server should handle the Apple event. You request a user interaction level from
- the server and specify whether the server can directly switch to the foreground
- if user interaction is needed, whether your application is willing to wait for a
- reply Apple event, whether reconnection is allowed, and whether your application
- wants a return receipt for the Apple event.
-
- You specify these options in the sendMode parameter to AESend. Here are the
- constants that represent these options.
-
- CONST kAENoReply = $00000001; {client doesn't want reply}
- kAEQueueReply = $00000002; {client wants to receive }
- { reply in event queue}
- kAEWaitReply = $00000003; {client wants to receive }
- { the reply directly and }
- { will give up the processor}
- kAENeverInteract = $00000010; {server should not }
- { interact with user}
- kAECanInteract = $00000020; {server can interact }
- { with user when needed}
- kAEAlwaysInteract = $00000030; {server can always }
- { interact with user}
- kAECanSwitchLayer = $00000040; {interaction may directly }
- { bring server to the front}
- kAEDontReconnect = $00000080; {if error, don't reconnect}
- kAEWantReceipt = nReturnReceipt; {client wants a return }
- { receipt}
-
- If your application wants a reply Apple event, specify the kAEQueueReply or
- kAEWaitReply flag. If your application wants to receive the reply Apple event in
- its event queue, use kAEQueueReply. If your application wants to receive the
- reply Apple event in the reply parameter of AESend and is willing to give up the
- processor while waiting for the reply, use kAEWaitReply. If your application
- does not want a reply Apple event and does not need to wait for the server to
- handle the Apple event, specify kNoReply.
-
- In most cases, your application should use kAEWaitReply or kAENoReply. You
- should not use kAEQueueReply if your application is sending an Apple event to
- itself.
-
- If your application specifies kAENoReply or kAEQueueReply, the AESend function
- returns immediately after using the Event Manager to send the event. In this
- case, a noErr result code from AESend indicates that the Apple event was
- successfully sent by the Event Manager; it does not mean that the server
- accepted or handled the Apple event.
-
- Also, the reply parameter to AESend does not contain valid data on return from
- AESend if your application specifies kAENoReply or kAEQueueReply. The kAENoReply
- flag indicates that the Apple Event Manager will not return the reply Apple
- event to your application. The kAEQueueReply flag indicates that your
- application wants to receive the reply in its event queue rather than through
- the reply parameter of AESend.
-
- If your application specifies kAEWaitReply, the Apple Event Manager uses the
- Event Manager to send the event. The Apple Event Manager then calls the
- WaitNextEvent function on behalf of your application, causing your application
- to yield the processor. This gives the server application a chance to receive
- and handle the Apple event. Your application continues to yield the processor
- until the server handles the Apple event or the request times out.
-
- You use one of the three flags—kAENeverInteract, kAECanInteract, or
- kAEAlwaysInteract—to specify whether the server should interact with the user
- when handling the Apple event. Specify kAENeverInteract if the server should not
- interact with the user when handling the Apple event. You might specify this
- constant if you don’t want the user to be interrupted while the server is
- handling the Apple event.
-
- Use the kAECanInteract flag if the server should interact with the user when
- necessary—for example, if the user needs to supply information to the server.
- Use the kAEAlwaysInteract flag if the server should interact with the user even
- when no information is needed from the user. Note that it is the responsibility
- of the server and client applications to agree on how to interpret the
- kAEAlwaysInteract flag.
-
- If the client application does not set any one of the user interaction flags,
- the Apple Event Manager sets a default, depending on the location of the target
- of the Apple event. If the server application is on a remote computer, the Apple
- Event Manager sets the kAENeverInteract flag as the default. If the target of
- the Apple event is on the local computer, the Apple Event Manager sets the
- kAECanInteract flag as the default.
-
- The server application should call AEInteractWithUser if it needs to interact
- with the user. If user interaction is allowed, the Apple Event Manager brings
- the server to the front if it is not already the foreground process. If the
- kAECanSwitchLayer flag is set and the principle of user control permits, the
- Apple Event Manager directly brings the server application to the front. If the
- action is contrary to the principle of user control, the Apple Event Manager
- posts a notification request to inform the user to bring the server application
- to the front.
-
- You should specify the kAECanSwitchLayer flag only when the client and server
- applications reside on the same computer. In general, you should not set this
- flag if it would be confusing or inconvenient to the user for the server
- application to unexpectedly come to the front.
-
- Specify the kAEDontReconnect flag if the Apple Event Manager should not
- reconnect if it receives a session closed error from the PPC Toolbox. If you
- don’t set this flag, the Apple Event Manager automatically attempts to reconnect
- and reestablish the session.
-
- Specify the kAEWantReceipt flag if your application wants notification that the
- server did not accept the Apple event. If you specify this flag, the AESend
- function returns the errAEEventNotHandled result code if the server did not
- accept the Apple event.
-
- Listing 6-17 illustrates how to send a Multiply event (an imaginary Apple event
- for multiplying two long integers). It first creates an Apple event, adds
- parameters containing the numbers to multiply, then sends it, specifying various
- options. It also illustrates how to handle the reply Apple event that contains
- the result.
-
- Note: If you want to send Apple events, your application must also handle the
- required Apple events. See “Handling the Required Apple Events” earlier in
- this
- chapter for information on how to support the required Apple events.
-
- ¿ Listing 6-17 Sending an Apple event
-
- FUNCTION MySendMultiplyEvent (serverAddress: AEAddressDesc;
- firstOperand: LongInt; secondOperand:
- LongInt; replyResultLongInt: LongInt)
- : OSErr;
- CONST
- kArithmeticClass = 'ARTH'; {event class for arithmetic }
- { Apple events}
- kMultipyEventID = 'MULT'; {event ID for Multiply event}
- keyMultOperand1 = 'OPN1'; {keyword for first parameter }
- keyMultOperand2 = 'OPN2'; {keyword for second parameter }
-
- VAR
- theAppleEvent: AppleEvent;
- reply: AppleEvent;
- returnedType: DescType;
- actualSize: LongInt;
- BEGIN
- myErr := AECreateAppleEvent(kArithmeticClass, kMultiplyEventID,
- ServerAddress, kAutoGenerateReturnID,
- kAnyTransactionID, theAppleEvent);
- IF myErr <> noErr THEN
- DoError(myErr); {failed to create the event}
- {add the first operand}
- myErr := AEPutParamPtr(theAppleEvent, keyMultOperand1,
- typeLongInteger, @firstOperand,
- SizeOf(firstOperand));
- IF myErr <> noErr THEN
- DoError(myErr); {failed to add first parameter - be sure to}
- { dispose of the event before leaving routine}
- {add the second operand with the proper keyword}
- myErr := AEPutParamPtr(theAppleEvent, keyMultOperand2,
- typeLongInteger, @secondOperand,
- SizeOf(secondOperand));
- IF myErr <> noErr THEN
- DoError(myErr); {Be sure to dispose of the event and first }
- { parameter before leaving routine}
- myErr := AESend(theAppleEvent, reply, kAEWaitReply + kAENeverInteract,
- kAENormalPriority, 120, @myIdleFunction, NIL);
- IF myErr = noErr THEN {Apple event successfully sent}
- BEGIN {check if it was successfully handled }
- { get result code returned by the server’s handler}
- myErr := AEGetParamPtr(reply, keyErrorNumber, typeLongInteger,
- returnedType, @errNumber,
- Sizeof(errNumber) );
- IF (myErr = errAEDescNotFound) | (errNumber = noErr) THEN
- {If keyErrorNumber doesn’t exist or server returned noErr }
- BEGIN { then the Apple event was successfully handled. }
- { The reply Apple event contains the result in }
- { the direct parameter}
- myErr := AEGetParamPtr(reply, keyDirectObject, typeInteger,
- returnedType, @replyResultLongInt,
- SizeOf(replyResultLongInt), actualSize);
- MySendMultiplyEvent := noErr;
- Exit(MySendMultiplyEvent);
- END;
- ELSE
- BEGIN {server returned an error, so get error string}
- myErr := AEGetParamPtr(reply, keyErrorString, typeChar,
- returnedType, @errStr,
- Sizeof(errStr));
- IF myErr = noErr THEN
- MyDisplayError(errStr);
- END;
- END;
- ELSE
- BEGIN
- {either the Apple event wasn’t successfully dispatched, }
- { the request timed out, the user canceled, or other error}
- END;
- END;
- MySendMultiplyEvent := myErr;
- END;
-
- The code in Listing 6-17 first creates an Apple event with kArithmeticClass as
- the event class and kMultipyEventID as the event ID. It also specifies the
- server of the Apple event. See “Specifying a Target Address” in an earlier
- section for information on various ways to specify a target address. See
- “Creating Apple Events” earlier in this chapter for more information on how to
- create an Apple event.
-
- The Multiply event shown in Listing 6-17 contains two parameters, each of which
- specifies a number to multiply. See “Adding Parameters to an Apple Event”
- earlier in this chapter for examples of how to specify the parameters for the
- AEPutParamPtr function.
-
- After adding the parameters to the event, the code uses AESend to send the
- event. The first parameter to AESend specifies the Apple event to send—in this
- example, the Multiply event. The next parameter specifies the reply Apple event.
-
-
- This example specifies kAEWaitReply in the third parameter, indicating that the
- client is willing to yield the processor for the specified timeout value (120
- ticks, or 2 seconds). The kAENeverInteract flag indicates that the server should
- not interact with the user when processing the Apple event. The Multiply event
- is sent using normal priority, meaning it is placed at the end of the event
- queue. You can specify the kAEHighPriority flag to place the event in the front
- of the event queue.
-
- The next to last parameter specifies the address of an idle function. If you
- specify kAEWaitReply you should provide an idle function. This function should
- process any update events, null events, operating-system events, or activate
- events that occur while your application is waiting for a reply. See “Writing
- an Idle Function” later in this chapter for sample code that shows an idle
- function.
-
- The last parameter to AESend specifies a filter function. You can supply a
- filter function to filter high-level events that your application might receive
- while waiting for a reply Apple event. You can specify NIL for this parameter if
- you do not need to filter high-level events while waiting for a reply. See
- “Writing a Reply Filter Function” later in this chapter for more information.
-
- If AESend returns a noErr result code and your application specified
- kAEWaitReply, you should first see whether a result code was returned from the
- handler routine by checking the reply Apple event for the existence of the
- parameter whose keyword is keyErrorNumber. If the keyErrorNumber parameter does
- not exist or contains the noErr result code, you can use AEGetParamPtr to get
- the parameter you’re interested in from the reply Apple event.
-
- The code in Listing 6-17 checks the function result of AESend. If AESend returns
- noErr, the code then checks the replyErrorNumber parameter of the reply Apple
- event to determine whether the server successfully handled the Apple event. If
- this parameter exists and indicates an error occurred, then the code gets the
- error string out of the keyErrorString parameter. Otherwise, the server
- performed the request, and the reply Apple event contains the answer to the
- multiplication request.
-
- When you are done using the Apple event specified in the AESend function and
- finished with the reply Apple event, you must dispose of their descriptor
- records using the AEDisposeDesc function.
- _______________________________________________________________________________
-
- æKY Dealing…With…Timeouts
- æC »Dealing With Timeouts The Apple Event Manager
- _______________________________________________________________________________
-
- When your application calls AESend and chooses to wait for the server to handle
- the Apple event, it can also specify the maximum amount of time that it is
- willing to wait for a response. You can specify a timeout value in the timeout
- parameter to AESend. You can either specify a particular length of time, in
- ticks, that your application is willing to wait, or you can specify the
- kNoTimeOut constant or the kAEDefaultTimeout constant.
-
- Use the kNoTimeOut constant to indicate that your application is willing to wait
- forever for a response from the server. You should use this value only if your
- application is guaranteed that the server will respond in a reasonable amount of
- time. You should also implement a method of checking if the user wants to
- cancel. The idle function that you specify as a parameter to AESend should check
- the event queue for any instances of Command-period and immediately return TRUE
- as its function result if it finds a request to cancel in the event queue.
-
- Use the kAEDefaultTimeout constant if you want the Apple Event Manager to use a
- default value for the timeout value. The Apple Event Manager uses a timeout
- value of about one minute if you specify this constant.
-
- Note that if you set the kAEWaitReply flag and the server doesn’t have a handler
- for the Apple event, AESend returns immediately with the errAEEventNotHandled
- result code.
-
- If the server doesn’t respond within the length of time specified by the timeout
- value, AESend returns the errAETimeOut result code. This result code does not
- necessarily mean that the server failed to perform the requested action; it only
- means that the server did not complete processing within the specified time. The
- server might still be processing the Apple event, and it might still send a
- reply.
-
- If the server finishes processing the Apple event sometime after the time
- specified in the timeout parameter has expired, it returns a reply Apple event
- to AEProcessAppleEvent. The Apple Event Manager then returns the reply to the
- client in the reply parameter that the client originally passed to the AESend
- function.
-
- This means your application can continue to check the reply Apple event to see
- if the server has responded, even after the time expires. If the server has not
- yet sent the reply when the client attempts to extract data from the reply Apple
- event, the Apple Event Manager functions return the errAEReplyNotArrived result
- code. Once the reply Apple event returns from the server, the client can extract
- the data in the reply.
-
- Additionally, the server can determine the timeout value specified by the client
- by examining the keyTimeoutAttr attribute in the Apple event. You can use the
- value of this attribute as a rough estimate of how much time your handler has to
- respond. You can assume that your handler has less time to respond than the
- timeout value, because transmitting the Apple event uses some of the available
- time, as does transmitting the reply Apple event back to the client.
-
- If your handler needs more time than is specified in the keyTimeoutAttr
- attribute, you can reset the timer by using the AEResetTimer function. This
- function resets the timeout value of an Apple event to its starting value.
-
- _______________________________________________________________________________
-
- æKY Writing…an…Idle…Function
- æC »Writing an Idle Function The Apple Event Manager
- _______________________________________________________________________________
-
- This section describes how to write an idle function when using the AESend or
- AEInteractWithUser functions.
-
- When your application sends an Apple event, you can wait for the server
- application to receive and finish handling the Apple event, or you can continue
- processing. If your application chooses to continue processing, the AESend
- function returns immediately after using the Event Manager to send the event. If
- your application chooses to wait for the server to handle the event, the AESend
- function does not return until either the server application finishes handling
- the Apple event or a specified amount of time expires.
-
- Your application specifies its preferences by setting flags in the sendMode
- parameter to AESend. Your application can specify kAENoReply if it does not want
- to receive a reply, kAEQueueReply if it wants to receive the reply in its event
- queue, or kAEWaitReply if it wants the reply returned in the reply parameter of
- AESend and is willing to give up the processor while waiting for the reply.
-
- If your application specifies the kAEWaitReply flag, the AESend function calls
- WaitNextEvent on behalf of your application. This yields the processor to other
- processes, so that the server has an opportunity to receive and process the
- Apple event sent by your application. While your application is waiting for a
- reply, it cannot receive events unless it provides an idle function.
-
- If your application provides a pointer to an idle function as a parameter to the
- AESend function, AESend calls your idle function whenever an update event, null
- event, operating-system event, or activate event is received for your
- application. Your application can process high-level events that it receives
- while waiting for a reply by providing a reply filter function. See the next
- section, “Writing a Reply Filter Function,” for more information.
-
- In a similar manner, when your application calls the AEInteractWithUser
- function, your application can also yield the processor. If AEInteractWithUser
- needs to post a notification request to bring your application to the front,
- your application yields the processor until the user brings your application to
- the front. To receive events while waiting for the user to bring your
- application to the front, you must provide an idle function.
-
- If your application provides a pointer to an idle function as a parameter to the
- AEInteractWithUser function, AEInteractWithUser calls your idle function
- whenever an update event, null event, operating-system event, or activate event
- is received for your application.
-
- An idle function must use this syntax:
-
- FUNCTION MyIdleFunction (VAR theEventRecord: EventRecord;
- VAR sleepTime: LongInt;
- VAR mouseRgn: RgnHandle) : Boolean;
-
- The parameter theEventRecord is the event record of the event to process. The
- sleepTime parameter and mouseRgn parameters are values that your idle function
- sets the first time it is called; thereafter they contain the values your
- function set. Your idle function should return a Boolean value that indicates
- whether your application wishes to continue waiting. Set the function result to
- TRUE if your application is no longer willing to wait for a reply from the
- server or for the user to bring the application to the front. Set the function
- result to FALSE if your application is still willing to wait.
-
- The first time your idle function is called, it receives a null event. At this
- time, you should set the values for the sleepTime and mouseRgn parameters. These
- parameters are used in the same way as the sleep and mouseRgn parameters of the
- WaitNextEvent function. Specify in the sleepTime parameter the amount of time
- (in ticks) during which your application agrees to relinquish the processor if
- no events are pending for it.
-
- In the mouseRgn parameter, you specify a screen region that determines the
- conditions in which your application is to receive notice of mouse-moved events.
- Your idle function receives mouse-moved events only if your application is the
- front application and the mouse strays outside the region you specify.
-
- Your idle function receives only update events, null events, operating-system
- events, and activate events. When your idle function receives a null event, it
- can use the idle time to update status reports, animate cursors, or perform
- similar tasks. If your idle function receives any of the other events, it should
- handle the event as it normally would if received in its event loop.
-
- Listing 6-18 shows an example of an idle function that can be used as an idle
- function for AESend or AEInteractWithUser. The idle function processes update
- events, null events, operating-system events, and activate events. The first
- time the function is called it receives a null event. At this time, it sets the
- sleepTime and mouseRgn parameters. The function continues to process events
- until the server finishes handling the Apple event or the user brings the
- application to the front.
-
- Your application should implement a method of checking to see if the user wants
- to cancel. The MyCancelInQueue function in Listing 6-18 checks the event queue
- for any instances of Command-period and immediately returns TRUE as its function
- result if it finds a request to cancel in the event queue.
-
- ¿ Listing 6-18 An idle function
-
- FUNCTION MyIdleFunction (VAR event: EventRecord;
- VAR sleeptime: LongInt;
- VAR mouseRgn: RgnHandle) : Boolean;
- VAR
- hiByte: CHAR;
- myErr: OSErr;
- BEGIN
- MyIdleFunction := FALSE;
- {the MyCancelInQueue function checks the event queue for Command-period}
- IF MyCancelInQueue THEN
- BEGIN
- MyIdleFunction := TRUE;
- Exit(MyIdleFunction );
- END;
- CASE event.what OF
- updateEvt,
- activateEvt, {every idle function should handle these kinds }
- kOSEvent: { of events}
- BEGIN
- AdjustCursor(event.where, gCursorRgn);
- DoEvent(event);
- END;
- nullEvent:
- BEGIN
- {Set the sleepTime and mouseRgn parameters}
- mouseRgn := gCursorRgn;
- sleeptime := 10; {use the correct value for your app}
- DoIdle; {the application’s idle handling}
- END
- END; {CASE}
- END;
- _______________________________________________________________________________
-
- æKY Writing…a…Reply…Filter…Function
- æC »Writing a Reply Filter Function The Apple Event Manager
- _______________________________________________________________________________
-
- If your application calls AESend and chooses to yield the processor to other
- processes while waiting for a reply, you can provide an idle function to process
- update, null, operating-system, and activate events and, additionally, you can
- provide a reply filter function to process high-level events. The previous
- section describes how an idle function processes events.
-
- Your reply filter function can process any high-level events that it is willing
- to handle while waiting for a reply Apple event. For example, your application
- can choose to handle Apple events from other processes while waiting. Note,
- however, that your application must maintain any necessary state information.
- Your reply filter function must not accept any Apple events that can change the
- state of your application and make it impossible to return to its previous
- state.
-
- A reply filter function must use this syntax:
-
- FUNCTION MyWaitReplyFilter (VAR theEventRecord: EventRecord;
- transactionID: LongInt; returnID: LongInt;
- sender: AEAddressDesc) : Boolean;
-
- The parameter theEventRecord is the event record for a high-level event. The
- next three parameters contain valid information only if the event is an Apple
- event. The transactionID parameter is the transaction ID for the Apple event.
- The returnID parameter is the return ID for the Apple event. The sender
- parameter contains the address of the application or process that sent the Apple
- event.
-
- Your reply filter function should return TRUE as the function result if you want
- to accept the Apple event; otherwise it should return FALSE. If your filter
- function returns TRUE, the Apple Event Manager calls the AEProcessAppleEvent
- function on behalf of your application, and your handler routine is called to
- process the Apple event.
- _______________________________________________________________________________
-
- æKY Writing…and…Installing…Coercion…Handlers
- æC »Writing and Installing Coercion Handlers The Apple Event Manager
- _______________________________________________________________________________
-
- When your application extracts data from a parameter, it can request that the
- Apple Event Manager return the data using a descriptor type that is different
- from the original descriptor type. For example, when extracting data from the
- direct parameter of the Open Documents event, you can request that the alias
- records be returned as file system specification records. The Apple Event
- Manager can automatically coerce many different types of data from one to
- another. Table 6-1 later in this section shows descriptor types and the sorts of
- coercion that the Apple Event Manager can perform.
-
- You can also provide your own routines, referred to as coercion handlers, to
- coerce other descriptor types. To install your own coercion handlers, use the
- AEInstallCoercionHandler function. You specify as parameters to this function
-
- • the descriptor type of the data coerced by the handler
-
- • the descriptor type of the resulting data
-
- • the address of the coercion handler for this descriptor type
-
- • a reference constant
-
- • a Boolean value that indicates whether your coercion handler expects the
- data to
- be specified as a descriptor record or as a pointer to the actual data
-
- • a Boolean value that indicates whether your coercion handler should be added
-
- to your application’s coercion table or the system coercion table
-
- The system coercion table is a table in the system heap that contains handlers
- that are available to all applications and processes running on the same
- computer. The handlers in your application’s coercion table are available only
- to your application. When the Apple Event Manager is attempting to coerce data,
- it first looks for a coercion handler in your application’s coercion table. If
- it cannot find a handler for the descriptor type, it looks in the system
- coercion table for a handler. If it doesn’t find a handler there either, it
- returns the errAEHandlerNotFound result code.
-
- Note: When an application calls a system coercion handler, the A5 register is
- set
- up for the calling application. For this reason, if you provide a system
- coercion
- handler, it should never use A5 global variables or anything that depends on
- a
- particular context; otherwise, the application that calls the system coercion
-
- handler may crash.
-
- You can provide a coercion handler that expects to receive the data in a
- descriptor record or a buffer referred to by a pointer. When you install your
- coercion handler, you specify how your handler wishes to receive the data. It’s
- more efficient for the Apple Event Manager to provide your coercion handler with
- a pointer to the data so, whenever possible, you should write your coercion
- handler so that it can accept a pointer to the data.
-
- A coercion handler that accepts a pointer to data must be a function with the
- following syntax:
-
- FUNCTION MyCoercePtr (typeCode: DescType; dataPtr: Ptr;
- dataSize: Size; toType: DescType;
- handlerRefcon: LongInt;
- VAR result: AEDesc) : OSErr;
-
- The typeCode parameter is the descriptor type of the original data. The dataPtr
- parameter is a pointer to the data to coerce; the dataSize parameter is the
- length, in bytes, of the data. The toType parameter is the desired descriptor
- type of the resulting data. The handlerRefcon parameter is a reference constant
- that is stored in the coercion table entry for the handler and passed to the
- handler by the Apple Event Manager whenever the handler is called. The result
- parameter is the resulting descriptor record returned by your coercion handler.
-
- Your coercion handler should coerce the data to the desired descriptor type and
- return the resulting data in the descriptor record specified by the result
- parameter. Your handler should return the noErr result code if your handler
- successfully performs the coercion, and a nonzero result code otherwise.
-
- A coercion handler that accepts a descriptor record must be a function with the
- following syntax:
-
- FUNCTION MyCoerceDesc (theAEDesc: AEDesc; toType: DescType;
- handlerRefcon: LongInt;
- VAR result: AEDesc) : OSErr;
-
- The parameter theAEDesc is the descriptor record that contains the data to be
- coerced. The toType parameter is the descriptor type of the resulting data. The
- handlerRefcon parameter is a reference constant that is stored in the coercion
- table entry for the handler and passed to the handler by the Apple Event Manager
- whenever the handler is called. The result parameter is the resulting descriptor
- record.
-
- Your coercion handler should coerce the data in the descriptor record to the
- desired descriptor type and return the resulting data in the descriptor record
- specified by the result parameter. Your handler should return an appropriate
- result code.
-
- Table 6-1 lists the descriptor types that the Apple Event Manager provides
- coercion for. The first column shows the descriptor type of the data to be
- coerced, and the second column shows the descriptor types that the Apple Event
- Manager can coerce it to.
-
- Note: For many Apple Event Manager functions, the Apple Event Manager
- attempts to coerce data to the descriptor type you specify even if the result
- is no
- longer meaningful. To ensure that no coercion is performed and that the
- descriptor type of the result is of the same descriptor type as the original,
- specify
- typeWildCard for the desired type.
-
- ¿ Table 6-1 Coercion handling provided by the Apple Event Manager
- _________________________________________________________
- Original Desired
- Description
- Descriptor type descriptor type
-
- typeChar typeInteger Any string
- that is a valid
- typeLongInteger
- representation of a number
- typeSMInt can
- be coerced into an
- typeSMFloat
- equivalent numeric value.
- typeShortInteger
- typeLongFloat
- typeShortFloat
- typeExtended
- typeComp
- typeMagnitude
-
- typeInteger typeChar Any numeric
- descriptor type
- typeLongInteger can be
- coerced into
- typeSMInt the
- equivalent text string.
- typeSMFloat
- typeShortInteger
- typeLongFloat
- typeShortFloat
- typeExtended
- typeComp
- typeMagnitude
-
- typeInteger typeInteger Any numeric
- descriptor type
- typeLongInteger typeLongInteger can be coerced into any
- other
- typeSMInt typeSMInt numeric
- descriptor type.
-
- typeSMFloat typeSMFloat
- typeShortInteger typeShortInteger
- typeLongFloat typeLongFloat
- typeShortFloat typeShortFloat
- typeExtended typeExtended
- typeComp typeComp
- typeMagnitude typeMagnitude
-
- typeTrue typeBoolean The result is the
- Boolean value
-
-
-
- typeFalse typeBoolean The result is the
- Boolean value
-
-
-
- typeEnumerated typeBoolean The enumerated value
- 'true'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- typeBoolean typeEnumerated The Boolean value FALSE
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- typeShortInteger typeBoolean A value of 1 becomes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- typeBoolean typeShortInteger A value of FALSE
- becomes 0.
-
-
-
-
-
-
-
-
- typeAlias typeFSS An alias
- record is coerced into a
-
-
-
-
-
-
- typeTemporaryID typeSectionH A temporary ID is coerced
- into
-
-
-
-
-
-
-
-
- typeAppleEvent typeAppParameters An Apple event is coerced
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- any descriptor type typeAEList A descriptor record is
- coerced
-
-
-
-
-
-
-
-
-
-
-
- typeAEList type of list item A descriptor list
- containing a
-
-
-
-
-
-
-
-
-
-
-
- _______________________________________________________________________________
-
- æKY The…Application…Died…Event
- æC »The Application Died Event The Apple Event Manager
- _______________________________________________________________________________
-
- If an application launched by your application terminates, either normally or as
- the result of an error, the Process Manager can notify your application by
- sending it an Apple event—the Application Died event. To receive this
- notification, you must set the acceptAppDied flag in your application’s 'SIZE'
- resource. (For a complete description of the 'SIZE' resource, see the Event
- Manager chapter in this volume.) See the Process Management chapter in this
- volume for information on how your application can launch other applications.
-
- Application Died—inform that an application has terminated
-
- Event class kCoreEventClass
-
- Event ID kAEApplicationDied
-
- Required parameters Keyword: keyErrorNumber
- Descriptor type:
- typeLongInteger
- Data: A
- sign-extended OSErr value. A value
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Keyword:
- keyProcessSerialNumber
- Descriptor type:
- typeProcessSerialNumber
- Data: The
- process serial number of the
-
-
-
-
-
- Requested action None. This Apple event is sent only to provide
- information.
-
- The Process Manager gets the value of the keyErrorNumber parameter from the
- system global variable DSErrCode. This value can be set either by the
- application before it terminates or by the Operating System (which can occur as
- the result of a hardware exception or other problem).
- _______________________________________________________________________________
-
- æKY Apple…Event…Manager…Routines…Volume…VI
- æC »Apple Event Manager Routines Volume VI The Apple Event Manager
- _______________________________________________________________________________
-
- This section describes the routines you use to manage Apple event dispatch
- tables, process Apple events, get parameters and attributes from Apple events,
- get data from Apple event data structures, create Apple event data structures,
- add parameters and attributes to Apple events, send Apple events, get
- information about and delete descriptor records, and coerce descriptor types.
- Result codes appear at the end of each function as applicable.
-
- _______________________________________________________________________________
-
- æKY Creating…and…Managing…the…Apple…Event…Dispatch…Tables
- æC »Creating and Managing the Apple Event Dispatch Tables The Apple Event Manager
- _______________________________________________________________________________
-
- An Apple event dispatch table contains entries that specify the event class and
- event ID that refer to one or more Apple events, the address of the handler
- routine that handles those Apple events, and a reference constant. You use the
- AEInstallEventHandler function to add entries to the Apple event dispatch table.
- Using this function sets up the initial mapping between the handlers in your
- application and the Apple events that they handle.
-
- If you need to remove any of your Apple event handlers after this mapping is
- established, you can use the AERemoveEventHandler function. To get the address
- of a handler currently in the Apple event dispatch table, use the
- AEGetEventHandler function.
-
- You use the AEInstallEventHandler function to add an entry to either the
- application or system Apple event dispatch table.
-
- To create an entry in the Apple event dispatch table, supply the event class,
- event ID, and address of the handler routine that handles Apple events of the
- specified event class and event ID. You also specify a reference constant that
- the Apple Event Manager passes to your handler routine whenever your handler
- processes an Apple event.
-
- FUNCTION AEInstallEventHandler (theAEEventClass: AEEventClass;
- theAEEventID: AEEventID; handler:
- EventHandlerProcPtr; handlerRefcon:
- LongInt; isSysHandler: Boolean) : OSErr;
-
- The parameters theAEEventClass and theAEEventID specify the event class and
- event ID of the Apple events to be handled by the handler for this dispatch
- table entry. For these parameters, you must provide one of the following
- combinations:
-
- • the event class and event ID of a single Apple event to be dispatched to the
-
- handler for this dispatch table entry
-
- • the typeWildCard constant for theAEEventClass and an event ID for
- theAEEventID, which indicates that Apple events from all event classes
- whose
- event IDs match theAEEventID should be dispatched to the handler for this
- dispatch table entry
-
- • an event class for theAEEventClass and the typeWildCard constant for
- theAEEventID, which indicates that all events from the event class
- theAEEventClass should be dispatched to the handler for this dispatch table
-
- entry
-
- • the typeWildCard constant for both the parameters theAEEventClass and
- theAEEventID, which specifies that all Apple events should be dispatched to
- the
- handler for this dispatch table entry
-
- The handler parameter is a pointer to an Apple event handler for this dispatch
- table entry. Note that a handler in the system dispatch table must reside in the
- system heap; this means that if the value of the isSysHandler parameter is TRUE,
- the handler parameter must point to a location in the system heap.
-
- The handlerRefcon parameter is a reference constant that is passed by the Apple
- Event Manager to the handler each time the handler is called. If your handler
- doesn’t use a reference constant, use 0 as the value of this parameter.
-
- The isSysHandler parameter specifies the Apple event dispatch table to which you
- want to add the handler. If the value of isSysHandler is TRUE, the Apple Event
- Manager adds the handler to the system Apple event dispatch table. Entries in
- the system Apple event dispatch table are available to all applications. If the
- value of isSysHandler is FALSE, the Apple Event Manager adds the handler to your
- application’s Apple event dispatch table. The application Apple event dispatch
- table is searched first; the system Apple event dispatch table is searched only
- if the necessary handler is not found in your application’s Apple event dispatch
- table.
-
- If there was already an entry in the specified event handler table for the same
- event class and event ID, it is replaced. Therefore, before installing a handler
- for a particular Apple event into the system dispatch table, use the
- AEGetEventHandler function to determine if the table already contains a handler
- for that event. If an entry exists, AEGetEventHandler returns a reference
- constant and a pointer to that event handler. Chain these to your event handler
- by providing pointers to the previous handler and its reference constant in the
- handlerRefcon parameter of AEInstallEventHandler. When your handler is finished,
- use these pointers to call the previous handler.
-
- If you put your handler code in the system heap or in your own heap, use the
- AERemoveHandler function to remove the handler when your application quits.
-
- Note: When an application calls a system Apple event handler, the A5 register
- is
- set up for the calling application. For this reason, if you provide a system
- Apple
- event handler, it should never use A5 global variables or anything that
- depends
- on a particular context; otherwise, the application that calls the system
- handler
- may crash.
-
- Result codes
- noErr 0 No error
- paramErr –50 Parameter error (handler pointer is
- NIL or odd)
- memFullErr –108 Not enough room in heap zone
-
- The AEGetEventHandler function gets an entry from an Apple event dispatch table.
-
- FUNCTION AEGetEventHandler (theAEEventClass: AEEventClass; theAEEventID:
- AEEventID; VAR handler: EventHandlerProcPtr;
- VAR handlerRefcon: LongInt; isSysHandler:
- Boolean) : OSErr;
-
- The parameter theAEEventClass is the value of the event class field of the
- dispatch table entry for the desired Apple event handler, and the parameter
- theAEEventID is the value of the event ID field of the dispatch table entry for
- the desired Apple event handler. You can use the typeWildCard constant for
- either or both of these parameters. (For an explanation of wildcard values, see
- the earlier description of the AEInstallEventHandler function.)
-
- In the handler parameter, the AEGetEventHandler function returns a pointer to
- the Apple event handler.
-
- In the handlerRefcon parameter, the AEGetEventHandler function returns the
- reference constant that is passed by the Apple Event Manager to the Apple event
- handler each time the handler is called.
-
- The isSysHandler parameter specifies the Apple event dispatch table from which
- to get the handler. If isSysHandler is TRUE, the AEGetEventHandler function
- returns the handler from the system dispatch table. If isSysHandler is FALSE,
- AEGetEventHandler returns the handler from your application’s dispatch table.
-
- Result codes
- noErr 0 No error
- errAEHandlerNotFound –1717 No handler found for an Apple
- event
-
- The AERemoveEventHandler function removes an entry from an Apple event dispatch
- table.
-
- FUNCTION AERemoveEventHandler (theAEEventClass: AEEventClass;
- theAEEventID: AEEventID; handler:
- EventHandlerProcPtr; isSysHandler:
- Boolean) : OSErr;
-
- The parameter theAEEventClass is the event class for the handler to be removed.
- The parameter theAEEventID is the event ID for the handler to be removed. You
- can use the typeWildCard constant for either or both of these parameters. (For
- an explanation of wildcard values, see the earlier description of the
- AEInstallEventHandler function.)
-
- The handler parameter is a pointer to the Apple event handler to be removed.
- Although the parameters theAEEventClass and theAEEventID would be sufficient to
- identify the handler to be removed, providing the handler parameter is a
- safeguard that ensures that you’re removing the correct handler.
-
- The isSysHandler parameter specifies the Apple event dispatch table from which
- to remove the handler. If TRUE, AERemoveEventHandler removes the handler from
- the system dispatch table. If FALSE, AERemoveEventHandler removes the handler
- from your application’s dispatch table.
-
- Result codes
- noErr 0 No error
- errAEHandlerNotFound –1717 No handler found for an Apple
- event
- _______________________________________________________________________________
-
- æKY Dispatching…Apple…Events
- æC »Dispatching Apple Events The Apple Event Manager
- _______________________________________________________________________________
-
- After receiving a high-level event (and optionally checking whether it is a type
- of high-level event other than an Apple event that your application might
- support), your application typically calls the AEProcessAppleEvent function to
- determine the type of Apple event received and to call the corresponding handler
- routine.
-
- The AEProcessAppleEvent function looks first in the application Apple event
- dispatch table and then in the system Apple event dispatch table for an entry
- that matches the event class and event ID of the specified Apple event. If
- AEProcessAppleEvent finds a matching entry, it calls the handler for that Apple
- event.
-
- FUNCTION AEProcessAppleEvent (theEventRecord: EventRecord) : OSErr;
-
- The parameter theEventRecord is the event record for the Apple event.
-
- If the AEProcessAppleEvent function cannot find a handler for an Apple event in
- either the application or system Apple event dispatch table, the Apple Event
- Manager returns the result code errAEEventNotHandled to the server application
- (as the result of the AEProcessAppleEvent function). The Apple Event Manager
- also returns this result code to the client application if the client is waiting
- for a reply.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in
- heap zone
- bufferIsSmall –607 Buffer is too small
- noOutstandingHLE –608 No outstanding high-level
- event
- errAECorruptData –1702 Data in an Apple event
- could not be read
- errAENewerVersion –1706 Need a newer version of the
- Apple Event
-
-
- errAENotAppleEvent –1707 Event is not an Apple event
- errAEHandlerNotFound –1708 A handler for the Apple event wasn’t
-
- found
- _______________________________________________________________________________
-
- æKY Getting…Parameters…and…Attributes…From…Apple…Events
- æC »Getting Parameters and Attributes From Apple Events The Apple Event Manager
- _______________________________________________________________________________
-
- You use the AEGetParamPtr and AEGetParamDesc functions to gain access to the
- parameters of an Apple event. You use the AEGetAttributePtr and
- AEGetAttributeDesc functions to gain access to the attributes of an Apple event.
-
- The AEGetParamPtr function uses a buffer to return the data contained in a
- specified parameter of an Apple event.
-
- FUNCTION AEGetParamPtr (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; desiredType: DescType; VAR typeCode:
- DescType; dataPtr: Ptr; maximumSize: Size;
- VAR actualSize: Size) : OSErr;
-
- The parameter theAppleEvent is the Apple event containing the desired parameter.
-
- The parameter theAEKeyword is the keyword that specifies the desired parameter.
-
- The desiredType parameter specifies the descriptor type of the resulting data;
- if the desired parameter is not of this type, the Apple Event Manager attempts
- to coerce it into this type. If the value of desiredType is typeWildCard, no
- coercion is performed, and the descriptor type of the returned data is the same
- as the descriptor type of the parameter. The returned data’s descriptor type is
- returned in the typeCode parameter.
-
- The dataPtr parameter is a pointer to the buffer for storing the returned data.
-
- The maximumSize parameter is the maximum length, in bytes, of the data to be
- returned. You must allocate at least this amount of storage for the buffer
- specified by the dataPtr parameter.
-
- The AEGetParamPtr function returns in the actualSize parameter the actual
- length, in bytes, of the data for the Apple event parameter. If this value is
- larger than the value of maximumSize, not all of the data for the Apple event
- parameter was returned.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in
- heap zone
- errAECoercionFail –1700 Data could not be coerced
- to the requested
-
-
-
- errAEDescNotFound –1701 Descriptor record was not
- found
- errAEWrongDataType –1703 Wrong descriptor type
- errAENotAEDesc –1704 Not a valid descriptor
- record
- errAEReplyNotArrived –1718 Reply has not yet arrived
-
- The AEGetParamDesc function returns the descriptor record for an Apple event
- parameter.
-
- FUNCTION AEGetParamDesc (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; desiredType: DescType;
- VAR result: AEDesc) : OSErr;
-
- The parameter theAppleEvent is the Apple event containing the desired parameter.
-
- The parameter theAEKeyword is the keyword that specifies the desired parameter.
-
- The desiredType parameter specifies the descriptor type of the resulting
- descriptor record; if the parameter is not of this type, the Apple Event Manager
- attempts to coerce it into this type. If the value of desiredType is
- typeWildCard, no coercion is performed, and the descriptor type of the resulting
- descriptor record is the same as the descriptor type of the Apple event’s
- parameter.
-
- The AEGetParamDesc function returns in the result parameter the resulting
- descriptor record. This function creates a new descriptor record by copying the
- descriptor record from the parameter. Your application is responsible for using
- the AEDisposeDesc function to dispose of the resulting descriptor record once
- you are finished using it.
-
- If the function returns a nonzero result code, a descriptor record with the
- typeNull descriptor type is returned. A descriptor record of this type does not
- contain any data.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in heap
- zone
- errAECoercionFail –1700 Data could not be coerced to
- the requested
-
- type
- errAEDescNotFound –1701 Descriptor type was not found
- errAENotAEDesc –1704 Not a valid descriptor record
- errAEReplyNotArrived –1718 Reply has not yet arrived
-
- The AEGetAttributePtr function uses a buffer to return the data contained in an
- Apple event attribute.
-
- FUNCTION AEGetAttributePtr (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; desiredType: DescType;
- VAR typeCode: DescType; dataPtr: Ptr;
- maximumSize: Size; VAR actualSize:
- Size) : OSErr;
-
- The parameter theAppleEvent is the Apple event containing the desired attribute.
-
- The parameter theAEKeyword is the keyword that specifies the desired attribute.
-
- The desiredType parameter is the descriptor type of the data to be returned; if
- the desired attribute is not of this type, the Apple Event Manager attempts to
- coerce it into this type. If the value of desiredType is typeWildCard, no
- coercion is performed, and the descriptor type of the returned data is the same
- as the descriptor type of the attribute. The returned data’s descriptor type is
- returned in the typeCode parameter.
-
- The dataPtr parameter is a pointer to the buffer for storing the data that is
- returned.
-
- The maximumSize parameter is the maximum length, in bytes, of the data to be
- returned.
-
- The AEGetAttributePtr function returns in the actualSize parameter the actual
- length, in bytes, of the data for the attribute. If this value is larger than
- the value of maximumSize, not all of the data for the attribute was returned.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in heap
- zone
- errAECoercionFail –1700 Data could not be coerced to
- the requested
-
- type
- errAEDescNotFound –1701 Descriptor type was not found
- errAENotAEDesc –1704 Not a valid descriptor record
- errAEReplyNotArrived –1718 Reply has not yet arrived
-
- The AEGetAttributeDesc function returns the descriptor record for an Apple event
- attribute.
-
- FUNCTION AEGetAttributeDesc (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; desiredType: DescType;
- VAR result: AEDesc) : OSErr;
-
- The parameter theAppleEvent is the Apple event containing the desired attribute.
-
- The parameter theAEKeyword is the keyword that specifies the desired attribute.
-
- The desiredType parameter is the descriptor type of the descriptor record to be
- returned; if the desired attribute is not of this type, the Apple Event Manager
- attempts to coerce it into this type. If the value of desiredType is
- typeWildCard, no coercion is performed, and the descriptor type of the resulting
- descriptor record is the same as the descriptor type of the attribute.
-
- The AEGetAttributeDesc function returns in the result parameter the resulting
- descriptor record. This function creates a new descriptor record by copying the
- descriptor record from the parameter. Your application is responsible for using
- the AEDisposeDesc function to dispose of the resulting descriptor record once
- you are finished using it.
-
- If the function returns a nonzero result code, a descriptor record with the
- typeNull descriptor type is returned. A descriptor record of this type does not
- contain any data.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in
- heap zone
- errAECoercionFail –1700 Data could not be coerced
- to the requested
-
-
-
- errAEDescNotFound –1701 Descriptor record was not
- found
- errAENotAEDesc –1704 Not a valid descriptor
- record
- errAEReplyNotArrived –1718 Reply has not yet arrived
- _______________________________________________________________________________
-
- æKY Counting…the…Items…in…Descriptor…Lists
- æC »Counting the Items in Descriptor Lists The Apple Event Manager
- _______________________________________________________________________________
-
- The AECountItems function counts the number of descriptor records in a
- descriptor list.
-
- FUNCTION AECountItems (theAEDescList: AEDescList; VAR theCount:
- LongInt) : OSErr;
-
- The parameter theAEDescList is the descriptor list to be counted.
-
- The AECountItems function returns the number of descriptor records in the list
- in the parameter theCount.
-
- Result codes
- noErr 0 No error
- errAENotAEDesc –1704 Not a valid descriptor record
- _______________________________________________________________________________
-
- æKY Getting…Items…From…Descriptor…Lists
- æC »Getting Items From Descriptor Lists The Apple Event Manager
- _______________________________________________________________________________
-
- You can use the AEGetNthPtr and AEGetNthDesc functions to gain access to the
- data in a descriptor list. You can use the AEGetArray function to get data from
- an array contained in a descriptor list.
-
- The AEGetNthPtr function uses a buffer to return the data for a descriptor
- record in a descriptor list.
-
- FUNCTION AEGetNthPtr (theAEDescList: AEDescList; index: LongInt;
- desiredType: DescType; VAR theAEKeyword:
- AEKeyword; VAR typeCode: DescType; dataPtr:
- Ptr; maximumSize: Size; VAR actualSize: Size) :
- OSErr;
-
- The parameter theAEDescList is the descriptor list containing the desired
- descriptor record.
-
- The index parameter specifies the position of the desired descriptor record in
- the list (for example, 2 specifies the second descriptor record).
-
- The desiredType parameter is the descriptor type of the resulting data; if the
- descriptor record is not of this type, the Apple Event Manager attempts to
- coerce it into this type. If the value of desiredType is typeWildCard, no
- coercion is performed, and the descriptor type of the resulting data is the same
- as the descriptor type of the original descriptor record.
-
- If you are getting data from a list of keyword-specified descriptor records, the
- keyword of the specified descriptor record is returned in the parameter
- theAEKeyword; otherwise, the value typeWildCard is returned.
-
- The returned data’s descriptor type is returned in the typeCode parameter.
-
- The dataPtr parameter is the pointer to the buffer for storing the data.
-
- The maximumSize parameter is the maximum length, in bytes, of the data to be
- returned.
-
- The AEGetNthPtr function returns in the actualSize parameter the actual length,
- in bytes, of the data for the descriptor record. If this value is larger than
- the value of maximumSize, not all of the data for the descriptor record was
- returned.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in
- heap zone
- errAECoercionFail –1700 Data could not be coerced
- to the requested
-
-
-
- errAEDescNotFound –1701 Descriptor record was not
- found
- errAEWrongDataType –1703 Wrong descriptor type
- errAENotAEDesc –1704 Not a valid descriptor
- record
- errAEReplyNotArrived –1718 Reply has not yet arrived
-
- The AEGetNthDesc function returns a descriptor record from a descriptor list.
-
- FUNCTION AEGetNthDesc (theAEDescList: AEDescList; index: LongInt;
- desiredType: DescType; VAR theAEKeyword:
- AEKeyword; VAR result: AEDesc) : OSErr;
-
- The parameter theAEDescList is the descriptor list from which to get the
- descriptor record.
-
- The index parameter is the position of the descriptor record to get (for
- example, 2 specifies the second descriptor record in the list).
-
- The desiredType parameter is the descriptor type of the resulting data; if the
- descriptor record is not of this type, the Apple Event Manager attempts to
- coerce it into this type. If the value of desiredType is typeWildCard, no
- coercion is performed, and the descriptor type of the resulting descriptor
- record is the same as the descriptor type of the original descriptor record.
-
- If you are getting data from a list of keyword-specified descriptor records, the
- AEGetNthDesc function returns the keyword of the specified descriptor record in
- the parameter theAEKeyword; otherwise, AEGetNthDesc returns the typeWildCard
- constant.
-
- The AEGetNthDesc function returns in the result parameter the resulting
- descriptor record. This function creates a new descriptor record by copying the
- descriptor record from the parameter. Your application is responsible for using
- the AEDisposeDesc function to dispose of the resulting descriptor record once
- you are finished using it.
-
- If the function returns a nonzero result code, a descriptor record with the
- typeNull descriptor type is returned. A descriptor record of this type does not
- contain any data.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in heap
- zone
- errAECoercionFail –1700 Data could not be coerced to
- the requested
-
- type
- errAEDescNotFound –1701 Descriptor record was not found
- errAENotAEDesc –1704 Not a valid descriptor record
- errAEReplyNotArrived –1718 Reply has not yet arrived
-
- The AEGetArray function converts an Apple event array (an array created with the
- AEPutArray function and stored in a descriptor list) into the corresponding
- Pascal or C array.
-
- FUNCTION AEGetArray (theAEDescList: AEDescList; arrayType: AEArrayType;
- arrayPtr: AEArrayDataPointer; maximumSize: Size;
- VAR itemType: DescType; VAR itemSize: Size;
- VAR itemCount: LongInt) : OSErr;
-
- The parameter theAEDescList is the descriptor list from which to get the array.
-
- The arrayType parameter is the Apple event array type to be converted. This is
- specified by one of the following constants: kAEDataArray, kAEPackedArray,
- kAEHandleArray, kAEDescArray, or kAEKeyDescArray.
-
- The arrayPtr parameter is a pointer to the buffer for storing the array.
-
- The maximumSize parameter is the maximum length, in bytes, of the data to be
- returned.
-
- For packed, data, and handle arrays, the itemType parameter returns the
- descriptor type of the array elements that are returned.
-
- For packed and data arrays, the itemSize parameter returns the size, in bytes,
- of the array elements that are returned.
-
- The itemCount parameter returns the number of items in the resulting array.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in heap
- zone
- errAEWrongDataType –1703 Wrong descriptor type
- errAENotAEDesc –1704 Not a valid descriptor record
- errAEReplyNotArrived –1718 Reply has not yet arrived
- _______________________________________________________________________________
-
- æKY Getting…Data…From…AE…Records
- æC »Getting Data From AE Records The Apple Event Manager
- _______________________________________________________________________________
-
- You can use the AEGetKeyPtr and AEGetKeyDesc functions to get data and
- keyword-specified descriptor records out of an AE record or an Apple event.
-
- The AEGetKeyPtr function uses a buffer to return the data contained in a
- keyword-specified descriptor record. You can use this function to get data out
- of an AE record or an Apple event record.
-
- FUNCTION AEGetKeyPtr (theAERecord: AERecord; theAEKeyword: AEKeyword;
- desiredType: DescType; VAR typeCode: DescType;
- dataPtr: Ptr; maximumSize: Size; VAR actualSize:
- Size) : OSErr;
-
- The parameter theAERecord is the AE record from which to get data.
-
- The parameter theAEKeyword is the keyword that specifies the desired descriptor
- record.
-
- The desiredType parameter specifies the descriptor type of the resulting data;
- if the desired data is not of this type, the Apple Event Manager attempts to
- coerce it into this type. If the value of desiredType is typeWildCard, no
- coercion is performed, and the descriptor type of resulting data is the same as
- the descriptor type of the original data. The returned data’s descriptor type is
- returned in the typeCode parameter.
-
- The dataPtr parameter is a pointer to the buffer for storing the data.
-
- The maximumSize parameter is the maximum length, in bytes, of the data to be
- returned.
-
- The AEGetKeyPtr function returns in the actualSize parameter the actual length,
- in bytes, of the data for the keyword-specified descriptor record. If this value
- is larger than the value of maximumSize, not all of the data for the
- keyword-specified descriptor record was returned.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in heap
- zone
- errAECoercionFail –1700 Data could not be coerced to
- the requested
-
- type
- errAEDescNotFound –1701 Descriptor record was not found
- errAEWrongDataType –1703 Wrong descriptor type
- errAENotAEDesc –1704 Not a valid descriptor record
- errAEReplyNotArrived –1718 Reply has not yet arrived
-
- The AEGetKeyDesc function returns the descriptor record for a keyword-specified
- descriptor record. You can use this function to get a descriptor record out of
- an AE record or an Apple event.
-
- FUNCTION AEGetKeyDesc (theAERecord: AERecord; theAEKeyword: AEKeyword;
- desiredType: DescType; VAR result: AEDesc) :
- OSErr;
-
- The parameter theAERecord is the AE record from which to get the descriptor
- record.
-
- The parameter theAEKeyword is the keyword that specifies the descriptor record
- to be returned.
-
- The desiredType parameter specifies the descriptor type of the resulting
- descriptor record; if the original descriptor record is not of this type, the
- Apple Event Manager attempts to coerce it into this type. If the value of
- desiredType is typeWildCard, no coercion is performed, and the descriptor type
- of the resulting descriptor record is the same as the descriptor type of the
- original descriptor record.
-
- The AEGetKeyDesc function returns in the result parameter the resulting
- descriptor record. This function creates a new descriptor record by copying the
- descriptor record from the AE record. Your application is responsible for using
- the AEDisposeDesc function to dispose of the resulting descriptor record once
- you are finished using it.
-
- If the function returns a nonzero result code, a descriptor record with the
- typeNull descriptor type is returned. A descriptor record of this type does not
- contain any data.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in heap
- zone
- errAECoercionFail –1700 Data could not be coerced to
- the requested
-
- type
- errAEDescNotFound –1701 Descriptor record was not found
- errAENotAEDesc –1704 Not a valid descriptor record
- errAEReplyNotArrived –1718 Reply has not yet arrived
- _______________________________________________________________________________
-
- æKY Requesting…User…Interaction
- æC »Requesting User Interaction The Apple Event Manager
- _______________________________________________________________________________
-
- Your server application may need to interact with the user while processing an
- Apple event. Your application should use the AEInteractWithUser function before
- actually interacting with the user in response to an Apple event. Your
- application can also specify its user interaction preferences by using the
- AESetInteractionAllowed and AEGetInteractionAllowed functions.
-
- A server application uses the AESetInteractionAllowed function to specify user
- interaction preferences for responding to Apple events.
-
- FUNCTION AESetInteractionAllowed (level: AEInteractAllowed) : OSErr;
-
- The level parameter must be one of three flags: kAEInteractWithSelf,
- kAEInteractWithLocal, or kAEInteractWithAll.
-
- Specifying the kAEInteractWithSelf flag allows the server application to
- interact with the user in response to an Apple event only when the client
- application and server application are the same—that is, only when the
- application is sending the Apple event to itself.
-
- Specifying the kAEInteractWithLocal flag allows the server application to
- interact with the user in response to an Apple event only if the client
- application is on the same computer as the server application; this is the
- default if the AESetInteractionAllowed function is not used.
-
- Specifying the kAEInteractWithAll flag allows the server application to interact
- with the user in response to an Apple event sent from any client application on
- any computer.
-
- Result code
- noErr 0 No error
-
- The AEGetInteractionAllowed function returns a value that indicates the user
- interaction preferences for responding to an Apple event. The value returned is
- the interaction level set by a previous call to AESetInteractionAllowed. The
- default value of kAEInteractWithLocal is returned if your application has not
- used AESetInteractionAllowed to explicitly set the interaction level.
-
- FUNCTION AEGetInteractionAllowed (VAR level: AEInteractAllowed) :
- OSErr;
-
- The level parameter returns one of the following flags: kAEInteractWithSelf,
- kAEInteractWithLocal, or kAEInteractWithAll.
-
- The kAEInteractWithSelf flag indicates that the server application may interact
- with the user in response to an Apple event only when the client application and
- server application are the same—that is, only when the application is sending
- the Apple event to itself.
-
- The kAEInteractWithLocal flag indicates that the server application may interact
- with the user in response to an Apple event only if the client application is on
- the same computer as the server application. This is the default if your
- application has not used the AESetInteractionAllowed function to explicitly set
- the interaction level.
-
- The kAEInteractWithAll flag indicates that the server application may interact
- with the user in response to an Apple event sent from any client application on
- any computer.
-
- Result code
- noErr 0 No error
-
- A server application calls the AEInteractWithUser function before displaying a
- dialog box or alert box or otherwise interacting with the user. If the
- user-interaction preference settings permit the application to come to the
- foreground, this function brings your application to the front, either directly
- or by posting a notification request.
-
- FUNCTION AEInteractWithUser (timeOutInTicks: LongInt; nmReqPtr:
- QElemPtr; idleProc: IdleProcPtr) : OSErr;
-
- The timeOutInTicks parameter is the amount of time (in ticks) that your handler
- is willing to wait for a response from the user.
-
- The nmReqPtr parameter is a pointer to a Notification Manager record provided by
- your application. You can specify NIL for this parameter to get the default
- notification handling provided by the Apple Event Manager.
-
- The idleProc parameter is a pointer to your application’s idle function, which
- handles events while waiting for the Apple Event Manager to return control. For
- a description of how to write this function, see “Writing an Idle Function”
- earlier in this chapter.
-
- The AEInteractWithUser function checks to see if the client application set the
- kAENeverInteract flag for the Apple event and, if so, returns an error. If not,
- then the AEInteractWithUser function checks the server application’s preference
- set by the AESetInteractionAllowed function and compares it against the source
- of the Apple event—that is, whether it came from the same application, another
- application or process on the same computer, or an application or process
- running on another computer. AEInteractWithUser returns the
- errAENoUserInteraction result code if the user-interaction preferences don’t
- allow user interaction. If user interaction is allowed, the Apple Event Manager
- brings your application to the front, either directly or by posting a
- notification request. If AEInteractWithUser returns the noErr result code, then
- your application is in the front and is free to interact with the user.
-
- Result code
- noErr 0 No
- error
- errAETimeout –1712 Apple event timed
- out
- errAENoUserInteraction –1713 No user interaction allowed
- _______________________________________________________________________________
-
- æKY Requesting…More…Time…to…Respond…to…Apple…Events
- æC »Requesting More Time to Respond to Apple Events The Apple Event Manager
- _______________________________________________________________________________
-
- The AEResetTimer function resets the timeout value for an Apple event to its
- starting value. A server application can call this function when it knows it
- cannot fulfill a client application’s request (either by returning a result or
- by sending back a reply Apple event) before the client application is due to
- time out.
-
- FUNCTION AEResetTimer (reply: AppleEvent) : OSErr;
-
- The reply parameter is the default reply for an Apple event and is provided by
- the Apple Event Manager. When AEResetTimer is called, the Apple Event Manager
- uses the default reply to send a Reset Timer event to the client application;
- the Apple Event Manager for the client application intercepts this Apple event
- and resets the client application’s timer for the Apple event. (The Reset Timer
- event is never dispatched to a handler, and the client application does not need
- a handler for it.)
-
- Result code
- noErr 0 No error
- errAEReplyNotValid –1709 AEResetTimer was passed an invalid
- reply
- _______________________________________________________________________________
-
- æKY Suspending…and…Resuming…Apple…Event…Handling
- æC »Suspending and Resuming Apple Event Handling The Apple Event Manager
- _______________________________________________________________________________
-
- The AESuspendTheCurrentEvent function suspends the processing of the Apple event
- that is currently being handled.
-
- FUNCTION AESuspendTheCurrentEvent (theAppleEvent: AppleEvent) : OSErr;
-
- The parameter theAppleEvent is the Apple event whose handling is to be
- suspended. Although the Apple Event Manager doesn’t need the parameter
- theAppleEvent to identify the Apple event currently being handled, providing
- this parameter is a safeguard that ensures that you are suspending the correct
- Apple event.
-
- After a server application makes a successful call to the
- AESuspendTheCurrentEvent function, it is no longer required to return a result
- or a reply for the Apple event that was being handled. It can, however, return a
- result if it later calls the AEResumeTheCurrentEvent function to resume event
- processing.
-
- The Apple Event Manager does not automatically dispose of Apple events that have
- been suspended or of their default replies. (The Apple Event Manager does,
- however, automatically dispose of a previously suspended Apple event and its
- default reply if the server later resumes processing of the Apple event by
- calling the AEResumeTheCurrentEvent function.) If your server application does
- not resume processing of a suspended Apple event, it is responsible for using
- the AEDisposeDesc function to dispose of both the Apple event and its default
- reply when you are finished with them.
-
- Result code
- noErr 0 No error
-
- The AEResumeTheCurrentEvent function informs the Apple Event Manager that your
- application wants to resume the handling of a previously suspended Apple event
- or that it has completed the handling of the Apple event.
-
- FUNCTION AEResumeTheCurrentEvent (theAppleEvent, reply: AppleEvent;
- dispatcher: EventHandlerProcPtr;
- handlerRefcon: LongInt) : OSErr;
-
- The parameter theAppleEvent is the Apple event whose processing is to be
- resumed.
-
- The reply parameter is the default reply that is automatically provided by the
- Apple Event Manager for the Apple event.
-
- The dispatcher parameter is one of the following:
-
- • a pointer to a routine for handling the event
-
- • the kAEUseStandardDispatch constant, which causes the Apple event to be
- dispatched in the way it was when it was first received
-
- • the kAENoDispatch constant, which tells the Apple Event Manager that the
- processing of the Apple event is complete and that it does not need to be
- dispatched
-
- If the value of the dispatcher parameter is not kAEUseStandardDispatch, the
- handlerRefcon parameter is a reference constant that is passed to the handler
- when the handler is called. If the value of the dispatcher parameter is
- kAEUseStandardDispatch, the Apple Event Manager ignores the handlerRefcon
- parameter and instead passes the reference constant that is stored in the Apple
- event dispatch table entry for the Apple event. (If you want to pass the same
- reference constant that is stored in the Apple event dispatch table, your
- application can obtain the reference constant by calling the AEGetEventHandler
- function.)
-
- Result code
- noErr 0 No error
-
- The AESetTheCurrentEvent function specifies the Apple event to be handled. There
- is generally no reason for your application to use this function. Instead of
- calling this function, your application should let the Apple Event Manager go
- through the dispatch tables to set the current Apple event.
-
- FUNCTION AESetTheCurrentEvent (theAppleEvent: AppleEvent) : OSErr;
-
- The parameter theAppleEvent is the Apple event that is to be handled.
-
- The AESetTheCurrentEvent function is used only to avoid going through the
- dispatch tables, and is used only in the following way:
-
- 1. An application suspends handling of an Apple event by calling the
- AESuspendTheCurrentEvent function.
-
- 2. The application calls the AESetTheCurrentEvent function to inform the
- Apple
- Event Manager that it is handling the Apple event that was previously
- suspended. It thereby makes the identity of the Apple event currently
- being
- handled available to routines that call the AEGetTheCurrentEvent
- function.
-
- 3. The application handles the Apple event. When it is finished, it calls
- the
- AEResumeTheCurrentEvent function with the value kAENoDispatch to tell
- the Apple Event Manager that the processing of the event is complete and
- that
- the Apple event does not need to be dispatched.
-
- Result code
- noErr 0 No error
-
- The AEGetTheCurrentEvent function returns the Apple event that is currently
- being handled. In many applications, the handling of an Apple event involves one
- or more long chains of calls to routines within the application. The
- AEGetTheCurrentEvent function makes it unnecessary for these calls to include
- the current Apple event as a parameter; the routines can simply call
- AEGetTheCurrentEvent to get the current Apple event when it is needed.
-
- FUNCTION AEGetTheCurrentEvent (VAR theAppleEvent: AppleEvent) :
- OSErr;
-
- This function returns the Apple event that is currently being handled in the
- parameter theAppleEvent.
-
- Result code
- noErr 0 No error
- _______________________________________________________________________________
-
- æKY Creating…Apple…Events
- æC »Creating Apple Events The Apple Event Manager
- _______________________________________________________________________________
-
- The AECreateAppleEvent function creates an Apple event with several important
- attributes but no parameters.
-
- FUNCTION AECreateAppleEvent (theAEEventClass: AEEventClass;
- theAEEventID: AEEventID; target:
- AEAddressDesc; returnID: Integer;
- transactionID: LongInt;
- VAR result: AppleEvent) : OSErr;
-
- The parameter theAEEventClass is the event class of the Apple event to be
- created.
-
- The parameter theAEEventID is the event ID of the Apple event to be created.
-
- The target parameter is the address of the server application. See “Specifying a
- Target Application” earlier in this chapter for information on how to address an
- Apple event.
-
- The returnID parameter is the return ID assigned to this Apple event; if the
- kAutoGenerateReturnID constant is used as the value, the Apple Event Manager
- assigns a return ID that is unique to the current session.
-
- The transactionID parameter is the transaction ID for this Apple event. A
- transaction refers to a sequence of Apple events that are sent back and forth
- between the client and server applications, beginning with the client’s initial
- request for a service. All Apple events that are part of a transaction must have
- the same transaction ID.
-
- The AECreateAppleEvent function returns in the result parameter the resulting
- Apple event. Your application is responsible for using the AEDisposeDesc
- function to dispose of the resulting Apple event once you are finished using it.
-
- If the function returns a nonzero result code, a descriptor record with the
- typeNull descriptor type is returned. A descriptor record of this type does not
- contain any data.
-
- Result code
- noErr 0 No error
- memFullErr –108 Not enough room in heap
- zone
- _______________________________________________________________________________
-
- æKY Creating…and…Duplicating…Descriptor…Records
- æC »Creating and Duplicating Descriptor Records The Apple Event Manager
- _______________________________________________________________________________
-
- The AECreateDesc function takes data and converts it into a descriptor record.
-
- FUNCTION AECreateDesc (typeCode: DescType; dataPtr: Ptr; dataSize:
- Size; VAR result: AEDesc) : OSErr;
-
- The typeCode parameter is the descriptor type for the resulting descriptor
- record.
-
- The dataPtr parameter is a pointer to the data for the descriptor record.
-
- The dataSize parameter is the length, in bytes, of the data for the descriptor
- record.
-
- The AECreateDesc function returns in the result parameter the resulting
- descriptor record. This function creates a new descriptor record by copying the
- descriptor record from the parameter. Your application is responsible for using
- the AEDisposeDesc function to dispose of the resulting descriptor record once
- you are finished using it. You normally do this after receiving a result from
- the AESend function.
-
- If the function returns a nonzero result code, a descriptor record with the
- typeNull descriptor type is returned. A descriptor record of this type does not
- contain any data.
-
- Result code
- noErr 0 No error
- memFullErr –108 Not enough room in heap
- zone
-
- The AEDuplicateDesc function makes a copy of a descriptor record.
-
- FUNCTION AEDuplicateDesc (theAEDesc: AEDesc; VAR result: AEDesc) :
- OSErr;
-
- The parameter theAEDesc is the descriptor record to be copied.
-
- The AEDuplicateDesc function returns in the result parameter the resulting
- descriptor record. This function creates a new descriptor record by copying the
- descriptor record from the parameter. Your application is responsible for using
- the AEDisposeDesc function to dispose of the resulting descriptor record once
- you are finished using it. You normally do this after receiving a result from
- the AESend function.
-
- If the function returns a nonzero result code, a descriptor record with the
- typeNull descriptor type is returned. A descriptor record of this type does not
- contain any data.
-
- It’s common for applications to send Apple events that have one or more
- attributes or parameters in common. For example, if you’re sending a series of
- Apple events to the same application, the address attribute is the same. In
- these cases, the most efficient way to create the necessary Apple events is to
- make a template Apple event that you can then copy—by calling the
- AEDuplicateDesc function—as needed. You then fill in or change the remaining
- parameters and attributes of the copy, send the copy by calling AESend, and then
- dispose of the copy—by calling AEDisposeDesc—after AESend returns a result.
-
- Result code
- noErr 0 No error
- memFullErr –108 Not enough room in heap
- zone
-
- _______________________________________________________________________________
-
- æKY Creating…Descriptor…Lists…and…AE…Records
- æC »Creating Descriptor Lists and AE Records The Apple Event Manager
- _______________________________________________________________________________
-
- The AECreateList function creates an empty descriptor list or AE record.
-
- FUNCTION AECreateList (factoringPtr: Ptr; factoredSize: Size; isRecord:
- Boolean; VAR resultList: AEDescList) : OSErr;
-
- You can compress descriptor lists—thereby saving both space and, in some cases,
- transmission time—by isolating data at the beginning of each descriptor record
- that is the same for all descriptor records in the list. This common data is
- sent only once for all the descriptor records in the list. When an application
- gets descriptor records from a compressed descriptor list, the Apple Event
- Manager automatically decompresses them.
-
- The factoringPtr parameter is a pointer to the data at the beginning of each
- descriptor that is the same for all descriptor records in the list. (The method
- for compressing descriptor lists is analogous to extracting the common factor
- from two or more numbers.) If there is no common data, or if you decide not to
- isolate the common data, provide NIL as the value of the factoringPtr
- parameter.
-
- The factoredSize parameter is the size of the common data. If there is no common
- data, or if you decide not to isolate the common data, the value of factoredSize
- must be 0.
-
- The isRecord parameter is a Boolean value that specifies the kind of list to
- create. If you set its value to TRUE, the Apple Event Manager creates an AE
- record. If you set its value to FALSE, the Apple Event Manager creates a
- descriptor list.
-
- The AECreateList function returns in the resultList parameter the resulting
- descriptor list or AE record. This function creates a new descriptor record by
- copying the descriptor record from the parameter. Your application is
- responsible for using the AEDisposeDesc function to dispose of the resulting
- descriptor record once you are finished using it. You normally do this after
- receiving a result from the AESend function.
-
- If the function returns a nonzero result code, a descriptor record with the
- typeNull descriptor type is returned. A descriptor record of this type does not
- contain any data.
-
- Result code
- noErr 0 No error
- paramErr –50 Error in parameter
- list
- memFullErr –108 Not enough room in heap
- zone
- _______________________________________________________________________________
-
- æKY Adding…Items…to…Descriptor…Lists
- æC »Adding Items to Descriptor Lists The Apple Event Manager
- _______________________________________________________________________________
-
- The AEPutPtr function takes data specified in a buffer and converts it to a
- descriptor record that it adds to a descriptor list.
-
- FUNCTION AEPutPtr (theAEDescList: AEDescList; index: LongInt; typeCode:
- DescType; dataPtr: Ptr; dataSize: Size) : OSErr;
-
- The parameter theAEDescList is the descriptor list to which to add a descriptor
- record.
-
- The index parameter is the position in the list for the descriptor record (for
- example, 2 specifies that it must be the second descriptor record). If there was
- already a descriptor record at that position, it is replaced. If the value of
- index is 0, the descriptor record is added at the end of the list.
-
- The typeCode parameter is the descriptor type for the resulting descriptor
- record.
-
- The dataPtr parameter is a pointer to the data for the descriptor record.
-
- The dataSize parameter is the length, in bytes, of the data for the descriptor
- record.
-
- Result code
- noErr 0 No error
- memFullErr –108 Not enough room in heap
- zone
- errAEWrongDataType –1703 Wrong descriptor type
- errAENotAEDesc –1704 Not a valid descriptor record
- errAEBadListItem –1705 Operation involving a list
- item failed
- errAEIllegalIndex –1719 Not a valid list index
-
- The AEPutDesc function adds a descriptor record to a descriptor list.
-
- FUNCTION AEPutDesc (theAEDescList: AEDescList; index: LongInt;
- theAEDesc: AEDesc) : OSErr;
-
- The parameter theAEDescList is the descriptor list to which you are adding a
- descriptor record.
-
- The index parameter is the position in the list for the descriptor record (for
- example, 2 specifies that it must be the second descriptor record). If there was
- already a descriptor record at that position, it is replaced. If the value of
- index is 0, the descriptor record is added to the end of the list.
-
- The parameter theAEDesc is the descriptor record to be added to the list.
-
- Result code
- noErr 0 No error
- memFullErr –108 Not enough room in heap
- zone
- errAEWrongDataType –1703 Wrong descriptor type
- errAENotAEDesc –1704 Not a valid descriptor record
- errAEBadListItem –1705 Operation involving a list
- item failed
- errAEIllegalIndex –1719 Not a valid list index
-
- The AEPutArray function puts the data for an Apple event array into a descriptor
- list.
-
- FUNCTION AEPutArray (theAEDescList: AEDescList; arrayType: AEArrayType;
- arrayPtr: AEArrayDataPointer; itemType: DescType;
- itemSize: Size; itemCount: LongInt) : OSErr;
-
- The parameter theAEDescList is the descriptor list into which to put the Apple
- event array. If there are any items already in the descriptor list, they are
- replaced.
-
- The arrayType parameter is the Apple event array type to be created. This is
- specified by one of the following constants: kAEDataArray, kAEPackedArray,
- kAEHandleArray, kAEDescArray, or kAEKeyDescArray. The kAEDataArray constant
- refers to an array of integers; kAEPackedArray refers to an array of characters;
- kAEHandleArray refers to an array of handles; kAEDescArray refers to an array of
- descriptor records; and kAEKeyDescArray refers to an array of keyword-specified
- descriptor records.
-
- If you are putting an array into a compressed descriptor list (see the
- description of the AECreateList function for information about compressing
- descriptor lists), the data for each array element must include the data that is
- common to all the descriptor records in the list. The Apple Event Manager
- automatically isolates the data you specified in the call to AECreateList that
- is common to all the elements of the array.
-
- The arrayPtr parameter is a pointer to the buffer containing the array.
-
- For packed, data, and handle arrays, the itemType parameter specifies the
- descriptor type of array items to be created.
-
- For packed and data arrays, the itemSize parameter specifies the size, in bytes,
- of the array items to be created.
-
- The itemCount parameter is the number of elements in the array.
-
- Result code
- noErr 0 No error
- memFullErr –108 Not enough room in heap
- zone
- errAEWrongDataType –1703 Wrong descriptor type
- errAENotAEDesc –1704 Not a valid descriptor record
- _______________________________________________________________________________
-
- æKY Adding…Data…to…AE…Records
- æC »Adding Data to AE Records The Apple Event Manager
- _______________________________________________________________________________
-
- The AEPutKeyPtr function takes a pointer to data, a descriptor type, and a
- keyword and converts them into a keyword-specified descriptor record that it
- adds to an AE record.
-
- FUNCTION AEPutKeyPtr (theAERecord: AERecord; theAEKeyword: AEKeyword;
- typeCode: DescType; dataPtr: Ptr; dataSize:
- Size) : OSErr;
-
- The parameter theAERecord is the AE record to which to add a keyword-specified
- descriptor record.
-
- The parameter theAEKeyword is the keyword specifying the descriptor record. If
- there was already a descriptor record with this keyword, it is replaced.
-
- The typeCode parameter is the descriptor type for the keyword-specified
- descriptor record.
-
- The dataPtr parameter is a pointer to the data for the keyword-specified
- descriptor record.
-
- The dataSize parameter is the length, in bytes, of the data for the
- keyword-specified descriptor record.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in
- heap zone
- errAEWrongDataType –1703 Wrong descriptor type
- errAENotAEDesc –1704 Not a valid descriptor
- record
- errAEBadListItem –1705 Operation involving a list
- item failed
-
- The AEPutKeyDesc function takes a descriptor record and a keyword and converts
- them into a keyword-specified descriptor record that it adds to an AE record.
-
- FUNCTION AEPutKeyDesc (theAERecord: AERecord; theAEKeyword: AEKeyword;
- theAEDesc: AEDesc) : OSErr;
-
- The parameter theAERecord is the AE record to which to add the keyword-specified
- descriptor record.
-
- The parameter theAEKeyword is the keyword specifying the descriptor record. If
- there was already a keyword-specified descriptor record with this keyword, it is
- replaced.
-
- The parameter theAEDesc is the descriptor record for the keyword-specified
- descriptor record.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in
- heap zone
- errAEWrongDataType –1703 Wrong descriptor type
- errAENotAEDesc –1704 Not a valid descriptor
- record
- errAEBadListItem –1705 Operation involving a list
- item failed
- _______________________________________________________________________________
-
- æKY Adding…Parameters…and…Attributes…to…Apple…Events
- æC »Adding Parameters and Attributes to Apple Events The Apple Event Manager
- _______________________________________________________________________________
-
- The AEPutParamPtr function takes a pointer to data, a descriptor type, and a
- keyword and converts them into a parameter that it adds to an Apple event.
-
- FUNCTION AEPutParamPtr (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; typeCode: DescType; dataPtr: Ptr;
- dataSize: Size) : OSErr;
-
- The parameter theAppleEvent is the Apple event to which you are adding a
- parameter.
-
- The parameter theAEKeyword is the keyword for the parameter. If there was
- already a parameter with this keyword in the Apple event, it is replaced.
-
- The typeCode parameter is the descriptor type for the parameter.
-
- The dataPtr parameter is a pointer to the data for the parameter.
-
- The dataSize parameter is the length, in bytes, of the data for the parameter.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in
- heap zone
- errAEWrongDataType –1703 Wrong descriptor type
- errAENotAEDesc –1704 Not a valid descriptor
- record
- errAEBadListItem –1705 Operation involving a list
- item failed
-
- The AEPutParamDesc function takes a descriptor record, and a keyword and
- converts them into a parameter that it adds to an Apple event.
-
- FUNCTION AEPutParamDesc (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; theAEDesc: AEDesc) : OSErr;
-
- The parameter theAppleEvent is the Apple event to which you are adding a
- parameter.
-
- The parameter theAEKeyword is the keyword for the parameter. If there was
- already a parameter with this keyword in the Apple event, it is replaced.
-
- The parameter theAEDesc is the descriptor record for the parameter.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in
- heap zone
- errAEWrongDataType –1703 Wrong descriptor type
- errAENotAEDesc –1704 Not a valid descriptor
- record
- errAEBadListItem –1705 Operation involving a list
- item failed
-
- The AEPutAttributePtr function takes a pointer to data, a descriptor type, and a
- keyword and converts them into an attribute that it adds to an Apple event.
-
- FUNCTION AEPutAttributePtr (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; typeCode: DescType; dataPtr:
- Ptr; dataSize: Size) : OSErr;
-
- The parameter theAppleEvent is the Apple event to which you are adding an
- attribute.
-
- The parameter theAEKeyword is the keyword of the attribute. If there was already
- an attribute with this keyword in the Apple event, it is replaced.
-
- The typeCode parameter is the descriptor type for the attribute.
-
- The dataPtr parameter is a pointer to the buffer containing the data to be
- assigned to the attribute.
-
- The dataSize parameter is the length, in bytes, of the data to be assigned to
- the attribute.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in
- heap zone
- errAECoercionFail –1700 Data could not be coerced
- to the requested
-
- type
- errAENotAEDesc –1704 Not a valid descriptor
- record
-
- The AEPutAttributeDesc takes a descriptor record and a keyword and converts them
- into an attribute that it adds to an Apple event.
-
- FUNCTION AEPutAttributeDesc (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; theAEDesc: AEDesc) : OSErr;
-
- The parameter theAppleEvent is the Apple event to which you are adding an
- attribute.
-
- The parameter theAEKeyword is the keyword of the attribute. If there was already
- an attribute with this keyword in the Apple event, it is replaced.
-
- The parameter theAEDesc is the descriptor record to be assigned to the
- attribute. The descriptor type of the specified descriptor record should match
- the defined descriptor type for that attribute. For example, the
- keyEventSourceAttr attribute has the typeShortInteger descriptor type.
-
- If the descriptor type required for the attribute is different than the
- descriptor type of the descriptor record, the Apple Event Manager attempts to
- coerce the descriptor record into the required type, with one exception: the
- Apple Event Manager does not attempt to coerce the data for an address
- attribute, thereby allowing applications to use their own address types.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in
- heap zone
- errAECoercionFail –1700 Data could not be coerced
- to the requested
-
- type
- errAENotAEDesc –1704 Not a valid descriptor
- record
- _______________________________________________________________________________
-
- æKY Sending…Apple…Events
- æC »Sending Apple Events The Apple Event Manager
- _______________________________________________________________________________
-
- The AESend function sends an Apple event.
-
- FUNCTION AESend (theAppleEvent: AppleEvent; VAR reply: AppleEvent;
- sendMode: AESendMode; sendPriority: AESendPriority;
- timeOutInTicks: LongInt; idleProc: IdleProcPtr;
- filterProc: EventFilterProcPtr) : OSErr;
-
- The parameter theAppleEvent specifies the Apple event to be sent.
-
- The reply parameter specifies the reply Apple event that is returned if you
- specify the kAEWaitReply flag in the sendMode parameter. (If you specify the
- kAEQueueReply flag in the sendMode parameter, you receive the reply Apple event
- in your event queue.) If you specify either the kAEQueueReply flag or the
- kAENoReply flag, the data in the reply Apple event returned by this function is
- not valid. If this function returns a nonzero result, it also returns in the
- reply parameter a descriptor record whose descriptor type is typeNull—that is,
- one that does not contain data. If you specify kAEWaitReply, your application is
- responsible for using the AEDisposeDesc function to dispose of the resulting
- descriptor record.
-
- The sendMode parameter allows you to specify the following: the reply mode for
- the Apple event (set with one of the constants kAENoReply, kAEQueueReply, or
- kAEWaitReply); the interaction mode (set with one of the constants
- kAENeverInteract, kAECanInteract, or kAEAlwaysInteract); the layer switch mode
- (set with the kAECanSwitchLayer constant); the reconnection mode (set with the
- kAEDontReconnect constant); and the return receipt mode (set with the
- kAEWantReceipt constant). You obtain the value for this parameter by adding the
- appropriate constants. These flags are stored in the interaction level
- attribute, whose keyword is keyInteractLevelAttr. The sendMode flags are
- described in a later part of this section.
-
- In the sendPriority parameter, you specify flags that determine whether the
- Apple event is put at the back of the event queue (the kAENormalPriority flag)
- or at the front of the queue (the kAEHighPriority flag).
-
- If the reply mode specified in the sendMode parameter is kAEWaitReply, or if a
- return receipt is requested, the timeOutInTicks parameter specifies the length
- of time (in ticks) that the client application is willing to wait for the reply
- or return receipt from the server application before timing out. Most
- applications should use the kAEDefaultTimeout constant, which tells the Apple
- Event Manager to provide an appropriate timeout duration. If the value of this
- parameter is kNoTimeOut, the Apple event never times out.
-
- The idleProc parameter specifies a pointer to a function for any tasks (such as
- displaying a wristwatch or spinning beach ball cursor) that the application
- performs while waiting for a reply or a return receipt (see “Writing an Idle
- Function” earlier in this chapter).
-
- The filterProc parameter specifies a pointer to a routine that accepts certain
- incoming Apple events that are received while the handler waits for a reply or a
- return receipt and filters out the rest (see “Writing a Reply Filter Function”
- earlier in this chapter).
-
- You can use one of the following flags in the sendMode parameter to specify the
- reply mode for an Apple event. Only one of these flags may be set.
-
- Flag Description
-
- kAENoReply Your application does not want a reply Apple event; the
-
- server processes your Apple event as
- soon as it has the
- opportunity.
-
- kAEQueueReply Your application wants a reply Apple event; the reply
- appears
- in your event queue as soon as the
- server has the
- opportunity to process and respond to
- your Apple event.
-
- kAEWaitReply Your application wants a reply Apple event and is
- willing to
- give up the processor while waiting for
- the reply; for
- example, if the server application is
- on the same computer as
- your application, your application
- yields the processor to
- allow the server to respond to your
- Apple event.
-
- You can communicate your user-interaction preferences to the server by
- specifying one of these flags in the sendMode parameter of the AESend function.
- Only one of these flags may be set.
-
- Flag Description
-
- kAENeverInteract The server application should never interact with the user
- in
- response to this Apple event. If this
- flag is set,
- AEInteractWithUser does not bring the
- server application to
- the foreground (this is the default
- when an Apple event is
- sent to a remote application).
-
- kAECanInteract The server application can interact with the user in
- response
- to this Apple event—by convention, if
- the user needs to
- supply information to the server. If
- this flag is set and the
- server allows interaction,
- AEInteractWithUser brings the
- server application to the foreground
- (this is the default
- when an Apple event is sent to a local
- application).
-
- kAEAlwaysInteract The server application can interact with the user in
- response
- to this Apple event—by convention, even
- if no information
- is needed from the user. If this flag
- is set and the server
- allows interaction, AEInteractWithUser
- brings the server
- application to the foreground. The
- Apple Event Manager
- does not distinguish between this flag
- and the
- kAECanInteract flag—distinguishing
- between them is the
- responsibility of the server
- application.
-
- The flags in the following list specify the layer switch mode, the reconnection
- mode, and the return receipt mode. Any of these flags may be set.
-
- Flag Description
-
- kAECanSwitchLayer If both the client and server allow interaction and this
- flag
- is set, AEInteractWithUser brings the
- server directly to the
- foreground if adherence to the
- principle of user control
- allows. If the action would be
- contrary to this principle,
- AEInteractWithUser uses the
- Notification Manager to
- request that user bring the server
- application to the
- foreground. If both the client and
- server allow interaction
- and this flag is not set,
- AEInteractWithUser always uses the
- Notification Manager to request that
- the user bring the
- server application to the foreground.
-
- kAEDontReconnect Specifies that the Apple Event Manager must not
- automatically try to reconnect if it
- receives a sessClosedErr
- result code from the PPC Toolbox.
-
- kAEWantReceipt The sender wants to receive a return receipt for this
- Apple
- event from the Event Manager.
- (Getting a return receipt
- means only that the receiving
- application accepted the
- Apple event; the Apple event may or
- may not be handled
- successfully after it is accepted).
- If the receiving application
- does not send a return receipt before
- the request times out,
- AESend returns errAETimeout as its
- function result.
-
- If the Apple Event Manager cannot find a handler for an Apple event in either
- the application or system Apple event dispatch table, it returns the result code
- errAEEventNotHandled to the server application (as the result of the
- AEProcessAppleEvent function). If the client is waiting for a reply, the Apple
- Event Manager also returns this result code to the client.
-
- AESend returns noErr as the function result if the Apple event was successfully
- sent by the Event Manager. A noErr result from AESend does not indicate that the
- Apple event was handled successfully; it only indicates that the Apple event was
- successfully sent by the Event Manager. If a result code other than noErr is
- returned by the handler, and if the client is waiting for a reply, it is
- returned in the keyErrorNumber parameter of the reply Apple event.
-
- Result codes
- noErr 0 No
- error
- memFullErr –108 Not enough
- room in heap zone
- connectionInvalid –609 Connection is
- invalid
- errAEEventNotHandled –1708 Event wasn’t handled by an
- Apple
-
-
-
- errAEUnknownSendMode –1710 Invalid sending mode was passed
- errAEWaitCanceled –1711 User canceled out of
- wait loop for
-
-
-
-
- errAETimeout –1712 Apple event timed
- out
- errAEUnknownAddressType –1716 Unknown Apple event address type
- _______________________________________________________________________________
-
- æKY Getting…the…Sizes…and…Descriptor…Types…of…Descriptor…Records
- æC »Getting the Sizes and Descriptor Types of Descriptor Records The Apple Event Manager
- _______________________________________________________________________________
-
- The AESizeOfNthItem function returns the size and descriptor type of a
- descriptor record in a descriptor list.
-
- FUNCTION AESizeOfNthItem (theAEDescList: AEDescList; index: LongInt;
- VAR typeCode: DescType; VAR dataSize: Size)
- : OSErr;
-
- The parameter theAEDescList is the descriptor list containing the descriptor
- record.
-
- The index parameter is the position of the descriptor record in the list (for
- example, 2 specifies the second descriptor record).
-
- The AESizeOfNthItem function returns the descriptor type of the descriptor
- record in the typeCode parameter .
-
- This function returns the length, in bytes, of the data contained in the
- descriptor record in the dataSize parameter.
-
- Result codes
- noErr 0 No error
- errAEDescNotFound –1701 Descriptor record was not found
- errAEReplyNotArrived –1718 Reply has not yet arrived
-
- The AESizeOfKeyDesc function returns the size and descriptor type of a
- keyword-specified descriptor record in an AE record.
-
- FUNCTION AESizeOfKeyDesc (theAERecord: AERecord; theAEKeyword:
- AEKeyword; VAR typeCode: DescType;
- VAR dataSize: Size) : OSErr;
-
- The parameter theAERecord is the AE record containing the desired
- keyword-specified descriptor record.
-
- The parameter theAEKeyword is the keyword that specifies the desired descriptor
- record.
-
- This function returns the descriptor type of the desired keyword-specified
- descriptor record in the typeCode parameter.
-
- This function returns the length, in bytes, of the data contained in the
- keyword-specified descriptor record in the dataSize parameter.
-
- Result codes
- noErr 0 No error
- errAEDescNotFound –1701 Descriptor record was not found
- errAENotAEDesc –1704 Not a valid descriptor
- record
- errAEReplyNotArrived –1718 Reply has not yet arrived
-
- The AESizeOfParam function returns the size and descriptor type of an Apple
- event parameter.
-
- FUNCTION AESizeOfParam (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; VAR typeCode: DescType;
- VAR dataSize: Size) : OSErr;
-
- The parameter theAppleEvent is the Apple event containing the parameter.
-
- The parameter theAEKeyword is the keyword that specifies the desired parameter.
-
- The function returns the descriptor type of the parameter in the typeCode
- parameter.
-
- The function returns the length, in bytes, of the data contained in the desired
- parameter in the dataSize parameter.
-
- Result codes
- noErr 0 No error
- errAEDescNotFound –1701 Descriptor record was not found
- errAENotAEDesc –1704 Not a valid descriptor
- record
- errAEReplyNotArrived –1718 Reply has not yet arrived
-
- The AESizeOfAttribute function returns the size and descriptor type of an Apple
- event attribute.
-
- FUNCTION AESizeOfAttribute (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; VAR typeCode: DescType;
- VAR dataSize: Size) : OSErr;
-
- The parameter theAppleEvent is the Apple event containing the attribute.
-
- The parameter theAEKeyword is the keyword that specifies the attribute.
-
- The function returns the descriptor type of the attribute in the typeCode
- parameter.
-
- The function returns the length, in bytes, of the data contained in the
- attribute in the dataSize parameter.
-
- Result codes
- noErr 0 No error
- errAEDescNotFound –1701 Descriptor record was not found
- errAENotAEDesc –1704 Not a valid descriptor
- record
- errAEReplyNotArrived –1718 Reply has not yet arrived
- _______________________________________________________________________________
-
- æKY Deleting…Descriptor…Records
- æC »Deleting Descriptor Records The Apple Event Manager
- _______________________________________________________________________________
-
- The AEDeleteItem function deletes a descriptor record from a descriptor list.
-
- FUNCTION AEDeleteItem (theAEDescList: AEDescList; index: LongInt) :
- OSErr;
-
- The parameter theAEDescList is the descriptor list containing the descriptor
- record to be deleted.
-
- The index parameter is the position of the descriptor record to delete (for
- example, 2 specifies the second item).
-
- Result codes
- noErr 0 No error
- errAEDescNotFound –1701 Descriptor record was not found
- errAENotAEDesc –1704 Not a valid descriptor
- record
- errAEBadListItem –1705 Operation involving a list
- item failed
-
- The AEDeleteKeyDesc function deletes a keyword-specified descriptor record from
- an AE record.
-
- FUNCTION AEDeleteKeyDesc (theAERecord: AERecord; theAEKeyword:
- AEKeyword) : OSErr;
-
- The parameter theAERecord is the AE record containing the keyword-specified
- descriptor record to be deleted.
-
- The parameter theAEKeyword is the keyword that specifies the descriptor record
- to be deleted.
-
- Result codes
- noErr 0 No error
- errAEDescNotFound –1701 Descriptor record was not found
- errAENotAEDesc –1704 Not a valid descriptor
- record
- errAEBadListItem –1705 Operation involving a list
- item failed
-
- The AEDeleteParam function deletes an Apple event parameter.
-
- FUNCTION AEDeleteParam (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword) : OSErr;
-
- The parameter theAppleEvent is the Apple event containing the parameter to be
- deleted.
-
- The parameter theAEKeyword is the keyword that specifies the parameter to be
- deleted.
-
- Result codes
- noErr 0 No error
- errAEDescNotFound –1701 Descriptor record was not found
- errAENotAEDesc –1704 Not a valid descriptor
- record
- errAEBadListItem –1705 Operation involving a list
- item failed
- _______________________________________________________________________________
-
- æKY Deallocating…Memory…for…Descriptor…Records
- æC »Deallocating Memory for Descriptor Records The Apple Event Manager
- _______________________________________________________________________________
-
- The AEDisposeDesc function deallocates the memory used by a descriptor record.
- Because all Apple event structures (except for keyword-specified descriptor
- records) are descriptor records, you can use AEDisposeDesc for any of them.
-
- FUNCTION AEDisposeDesc (VAR theAEDesc: AEDesc) : OSErr;
-
- The parameter theAEDesc is the descriptor record to deallocate.
-
- Result codes
- noErr 0 No error
- _______________________________________________________________________________
-
- æKY Coercing…Descriptor…Types
- æC »Coercing Descriptor Types The Apple Event Manager
- _______________________________________________________________________________
-
- <Intro section here? Why use these, and so on>
- The AECoercePtr function takes a pointer to data and a desired descriptor type
- and attempts to coerce the data into the desired descriptor type. If successful,
- it creates a descriptor record containing the newly coerced data.
-
- FUNCTION AECoercePtr (typeCode: DescType; dataPtr: Ptr; dataSize: Size;
- toType: DescType; VAR result: AEDesc) : OSErr;
-
- The typeCode parameter is the descriptor type of the source data.
-
- The dataPtr parameter is a pointer to the data to be coerced.
-
- The dataSize parameter is the length, in bytes, of the data to be coerced.
-
- The toType parameter is the desired descriptor type of the resulting descriptor
- record.
-
- The AECoercePtr function function returns in the result parameter the resulting
- descriptor record. This function creates a new descriptor record by copying the
- descriptor record from the parameter. Your application is responsible for using
- the AEDisposeDesc function to dispose of the resulting descriptor record once
- you are finished using it.
-
- If the function returns a nonzero result code, a descriptor record with the
- typeNull descriptor type is returned. A descriptor record of this type does not
- contain any data.
-
- Note: To avoid infinite recursion, AECoercePtr must never be called by an
- application-supplied coercion routine.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in heap zone
- errAECoercionFail –1700 Data could not be coerced to the
- requested
-
- The AECoerceDesc function coerces the data in a descriptor record to another
- descriptor type.
-
- FUNCTION AECoerceDesc (theAEDesc: AEDesc; toType: DescType; VAR result:
- AEDesc) : OSErr;
-
- The parameter theAEDesc is the descriptor record whose data is to be coerced.
-
- The toType parameter is the desired descriptor type of the resulting descriptor
- record.
-
- The AECoerceDesc function returns in the result parameter the resulting
- descriptor record. This function creates a new descriptor record by copying the
- descriptor record from the parameter. Your application is responsible for using
- the AEDisposeDesc function to dispose of the resulting descriptor record once
- you are finished using it.
-
- If the function returns a nonzero result code, a descriptor record with the
- typeNull descriptor type is returned. A descriptor record of this type does not
- contain any data.
-
- Note: To avoid infinite recursion, AECoerceDesc must never be called by an
- application-supplied coercion routine.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in heap zone
- errAECoercionFail –1700 Data could not be coerced to the
- requested
- descriptor
- type
- _______________________________________________________________________________
-
- æKY Creating…and…Managing…the…Coercion…Handler…Tables
- æC »Creating and Managing the Coercion Handler Tables The Apple Event Manager
- _______________________________________________________________________________
-
- The AEInstallCoercionHandler function installs a coercion handler routine in
- either the application or system coercion table.
-
- FUNCTION AEInstallCoercionHandler (fromType: DescType; toType: DescType;
- handler: ProcPtr; handlerRefcon:
- LongInt; fromTypeIsDesc: Boolean;
- isSysHandler: Boolean) : OSErr;
-
- The fromType parameter is the descriptor type of the data coerced by the
- handler, and the toType parameter is the descriptor type of the resulting data.
- If there was already an entry in the specified coercion handler table for the
- same source descriptor type and result descriptor type, it is replaced.
-
- Therefore, before installing a handler for a particular descriptor type into the
- system coercion table, use the AEGetCoercionHandler function to determine if the
- table already contains a handler for that descriptor type. If an entry exists,
- AEGetCoercionHandler returns a reference constant and a pointer to that handler.
- Chain these to your coercion handler by providing pointers to the previous
- handler and its reference constant in the handlerRefcon parameter of
- AEInstallCoercionHandler. When your handler is finished, use these pointers to
- call the previous handler.
-
- The handler parameter is a pointer to the coercion handler routine. Note that a
- handler in the system coercion table must reside in the system heap; this means
- that if the value of the isSysHandler parameter is TRUE, the handler parameter
- must point to a location in the system heap.
-
- The handlerRefcon parameter is a reference constant that is passed by the Apple
- Event Manager to the handler each time the handler is called. If your handler
- doesn’t expect a reference constant, use 0 as the value of this parameter.
-
- The fromTypeIsDesc parameter specifies the form of the data to be coerced. If
- its value is TRUE, the coercion handler expects the data to be passed as a
- descriptor record. If its value is FALSE, the coercion handler expects a pointer
- to the data to be coerced. Because it is more efficient for the Apple Event
- Manager to provide a pointer to data than to a descriptor record, all coercion
- routines should accept a pointer to data if possible.
-
- The isSysHandler parameter specifies the coercion table to which to add the
- handler. If its value is TRUE, the handler is added to the system coercion table
- and made available to all applications. If its value is FALSE, the handler is
- added to the application coercion table. Note that a handler in the system
- coercion table must reside in the system heap; this means that if the value of
- the isSysHandler parameter is TRUE, the handler parameter must point to a
- location in the system heap.
-
- If you put your handler code in the system heap or in your own heap, use the
- AERemoveCoercionHandler function to remove the handler when your application
- quits.
-
- Note: When an application calls a system Apple event handler, the A5 register
- is
- set up for the calling application. For this reason, if you provide a system
- Apple
- event handler, it should never use A5 global variables or anything that
- depends
- on a particular context; otherwise, the application that calls the system
- handler
- may crash.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in heap zone
-
- The AEGetCoercionHandler function returns the handler for a specified descriptor
- type coercion.
-
- FUNCTION AEGetCoercionHandler (fromType: DescType; toType: DescType;
- VAR handler: ProcPtr; VAR handlerRefcon:
- LongInt; VAR fromTypeIsDesc: Boolean;
- isSysHandler: Boolean) : OSErr;
-
- The fromType parameter is the descriptor type of the data coerced by the
- handler, while the parameter toType is the descriptor type of the resulting
- data.
-
- The function returns a pointer to the coercion handler routine in the handler
- parameter.
-
- The function returns a reference constant in the handlerRefcon parameter. The
- Apple Event Manager passes this reference constant to the handler each time the
- handler is called.
-
- If the function returns TRUE in the fromTypeIsDesc parameter, the coercion
- handler expects the data to be passed as a descriptor record. If the function
- returns FALSE, the coercion handler expects a pointer to the data.
-
- The isSysHandler parameter specifies the coercion table from which to get the
- handler. If its value is TRUE, the handler is taken from the system coercion
- table. If its value is FALSE, the handler is taken from the application coercion
- table.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in
- heap zone
- errAEHandlerNotFound –1717 No handler found for an Apple event
- or
- a
-
-
-
- The AERemoveCoercionHandler function removes a coercion handler routine from
- either the application or system coercion table.
-
- FUNCTION AERemoveCoercionHandler (fromType: DescType; toType: DescType;
- handler: ProcPtr; isSysHandler:
- Boolean) : OSErr;
-
- The fromType parameter is the descriptor type of the data coerced by the
- handler.
-
- The toType parameter is the descriptor type of the resulting data.
-
- The handler parameter is a pointer to the coercion handler routine. Although the
- fromType and toType parameters would be sufficient to identify the handler to be
- removed, providing the handler parameter is a safeguard to ensure that you
- remove the correct handler.
-
- The isSysHandler parameter specifies the coercion table from which to remove the
- handler. If its value is TRUE, the handler is removed from the system coercion
- table. If its value is FALSE, the handler is removed from the application
- coercion table.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Not enough room in
- heap zone
- errAEHandlerNotFound –1717 No handler found for an Apple event
- or
- a
-
-
- _______________________________________________________________________________
-
- æKY Creating…and…Managing…the…Special…Handler…Tables
- æC »Creating and Managing the Special Handler Tables The Apple Event Manager
- _______________________________________________________________________________
-
- The AEInstallSpecialHandler function installs a handler in a special handler
- table.
-
- FUNCTION AEInstallSpecialHandler (functionClass: AEKeyword; handler:
- ProcPtr; isSystemHandler: Boolean) :
- OSErr;
-
- The functionClass parameter is the keyword for the special handler that’s
- installed. There is currently only one value allowed for this parameter: the
- keyPreDispatch constant, which identifies a handler routine that is called
- immediately before the Apple Event Manager dispatches an Apple event. If there
- was already an entry in the specified special handler table for the same value
- of functionClass, it is replaced.
-
- The handler parameter is a pointer to the special handler. Note that a handler
- in the system handler table must reside in the system heap; this means that if
- the value of the isSysHandler parameter is TRUE, the handler parameter must
- point to a location in the system heap.
-
- The isSystemHandler parameter specifies the special handler table to which to
- add the handler. If its value is TRUE, the handler is added to the system
- handler table and made available to all applications. If its value is FALSE, the
- handler is added to the application handler table.
-
- If you put your handler code in the system heap or in your own heap, use the
- AERemoveSpecialHandler function to remove the handler when your application
- quits.
-
- Note: When an application calls a system Apple event handler, the A5
- register is
- set up for the calling application. For this reason, if you provide a system
- Apple
- event handler, it should never use A5 global variables or anything that
- depends
- on a particular context; otherwise, the application that calls the system
- handler
- may crash.
-
- Result codes
- noErr 0 No
- error
- paramErr –50 Parameter
- error (handler pointer is
-
-
-
-
- memFullErr –108 Not enough room
- in heap zone
- errAENotASpecialFunction –1714 Wrong keyword for a special
- function
-
- The AEGetSpecialHandler function returns a specified special handler.
-
- FUNCTION AEGetSpecialHandler (functionClass: AEKeyword; VAR handler:
- ProcPtr; isSystemHandler: Boolean) :
- OSErr;
-
- The functionClass parameter is the keyword that specifies the desired special
- handler. There is currently only one value allowed for this parameter: the
- keyPreDispatch constant, which identifies a handler routine that is called
- immediately before the Apple Event Manager dispatches an Apple event.
-
- The function returns a pointer to the special handler in the handler parameter.
-
- The isSystemHandler parameter specifies the special handler table from which to
- get the handler. If its value is TRUE, the handler is taken from the system
- handler table. If its value is FALSE, the handler is taken from the application
- handler table.
-
- Result codes
- noErr 0 No
- error
- memFullErr –108 Not enough room
- in heap zone
- errAENotASpecialFunction –1714 Wrong keyword for a special
- function
-
- The AERemoveSpecialHandler function removes a handler from a special handler
- table.
-
- FUNCTION AERemoveSpecialHandler (functionClass: AEKeyword; handler: ProcPtr;
- isSystemHandler: Boolean) : OSErr;
-
- The functionClass parameter is the keyword for the special handler to be
- removed. There is currently only one value allowed for the functionClass
- parameter: the keyPreDispatch constant, which identifies a handler routine that
- is called immediately before the Apple Event Manager dispatches an Apple event.
-
- The handler parameter is a pointer to the special handler to be removed.
- Although the functionClass parameter would be sufficient to identify the handler
- to be removed, providing the handler parameter is a safeguard to ensure that you
- remove the correct handler.
-
- The isSystemHandler parameter specifies the special handler table from which to
- remove the handler. If its value is TRUE, the handler is taken from the system
- handler table. If its value is FALSE, the handler is removed from the
- application handler table.
-
- Result codes
- noErr 0 No
- error
- memFullErr –108 Not enough room
- in heap zone
- errAENotASpecialFunction –1714 Wrong keyword for a special
- function
- _______________________________________________________________________________
-
- æKY Summary…of…the…Apple…Events…Manager…Volume…VI
- æC »Summary of the Apple Events Manager Volume VI The Apple Event Manager
- _______________________________________________________________________________
-
- Click the arrow in the lower-right corner of this window to see the summary
- sections of the constants, data types, and routines for the Apple Event Manager.
-
-
-
- _______________________________________________________________________________
-
- æKY Apple…Events…Manager…Constants
- æC »Apple Events Manager Constants The Apple Event Manager
- _______________________________________________________________________________
-
- CONST gestaltAppleEventsAttr = 'evnt'; {selector for Apple events}
- gestaltAppleEventsPresent
- = 0; {if set, Apple Event }
- { Manager is available}
-
- {Apple event descriptor types}
- typeBoolean = 'bool'; {Boolean value}
- typeChar = 'TEXT'; {unterminated string}
- typeSMInt = 'shor'; {16-bit integer}
- typeInteger = 'long'; {32-bit integer}
- typeSMFloat = 'sing'; {SANE Single}
- typeFloat = 'doub'; {SANE Double}
- typeLongInteger = 'long'; {32-bit integer}
- typeShortInteger = 'shor'; {16-bit integer}
- typeLongFloat = 'doub'; {SANE Double}
- typeShortFloat = 'sing'; {SANE Single}
- typeExtended = 'exte'; {SANE Extended}
- typeComp = 'comp'; {SANE Comp}
- typeMagnitude = 'magn'; {unsigned 32-bit integer}
- typeAEList = 'list'; {list of descriptor records}
- typeAERecord = 'reco'; {list of keyword-specified }
- { descriptor records}
- typeAppleEvent = 'aevt' {Apple event record}
- typeTrue = 'true'; {TRUE Boolean value}
- typeFalse = 'fals'; {FALSE Boolean value}
- typeAlias = 'alis'; {alias record}
- typeEnumerated = 'enum'; {enumerated data}
- typeType = 'type'; {descriptor type}
- typeAppParameters = 'appa'; {Process Manager launch }
- { parameters}
- typeProperty = 'prop'; {Apple event property}
- typeFSS = 'fss '; {file system specification}
- typeKeyword = 'keyw'; {Apple event keyword}
- typeSectionH = 'sect'; {Edition Manager section }
- { handle}
- typeTemporaryID = 'tid ' {temporary ID}
- typeWildCard = '****'; {matches any type}
- typeApplSignature = 'sign'; {application signature}
- typeSessionID = 'ssid'; {session ID}
- typeTargetID = 'targ'; {target ID}
- typeProcessSerialNumber
- = 'psn '; {process serial number}
- typeNull = 'null'; {NULL or nonexistent data}
-
- {keywords for Apple event parameters}
- keyDirectObject = '----'; {direct parameter}
- keyErrorNumber = 'errn'; {error number parameter}
- keyErrorString = 'errs'; {error string parameter}
- keyProcessSerialNumber = 'psn '; {process serial number param}
-
- {keywords for Apple event attributes}
- keyTransactionIDAttr = 'tran'; {transaction ID}
- keyReturnIDAttr = 'rtid'; {return ID}
- keyEventClassAttr = 'evcl'; {event class}
- keyEventIDAttr = 'evid'; {event ID}
- keyAddressAttr = 'addr'; {target application}
- keyOptionalKeywordAttr = 'optk'; {list of optional }
- { parameters for the }
- { Apple event}
- keyTimeoutAttr = 'timo'; {number of ticks the client }
- { will wait}
- keyInteractLevelAttr = 'inte'; {settings to allow Apple }
- { Event Mgr to bring }
- { server to foreground}
- keyEventSourceAttr = 'esrc'; {source application}
- keyMissedKeywordAttr = 'miss'; {first required parameter }
- { remaining in an Apple }
- { event}
-
- {keywords for special handlers}
- keyPreDispatch = 'phac'; {identifies a handler }
- { routine that is called }
- { immediately before the }
- { Apple Event Manager }
- { dispatches an Apple event}
-
- {event classes}
- kCoreEventClass = 'aevt'; {event class for core }
- { Apple events}
-
- {event IDs}
- kAEApplicationDied = 'obit' {event ID for Application }
- { Died event}
- kAEOpenApplication = 'oapp'; {event ID for Open }
- { Application event}
- kAEOpenDocuments = 'odoc'; {event ID for Open }
- { Documents event}
- kAEPrintDocuments = 'pdoc'; {event ID for Print }
- { Documents event}
- kAEQuitApplication = 'quit'; {event ID for Quit }
- { Application event}
- kAEAnswer = 'ansr'; {event ID for Apple event }
- { replies}
-
- {constants for setting the sendMode parameter of AESend and for }
- { the keyInteractLevelAttr attribute}
- kAENoReply = $00000001; {client doesn't want a reply}
- kAEQueueReply = $00000002; {client wants server to }
- { reply in event queue}
- kAEWaitReply = $00000003; {client wants a reply and }
- { will give up processor}
- kAENeverInteract = $00000010; {server application should }
- { not interact with user }
- { for this Apple event}
- kAECanInteract = $00000020; {server may interact with }
- { user for this Apple }
- { to supply information}
- { event}
- kAEAlwaysInteract = $00000030; {server may interact with }
- { user for this Apple event }
- { even if no information }
- { is required}
- kAECanSwitchLayer = $00000040; {server should come }
- { directly to foreground }
- { when appropriate}
- kAEDontReconnect = $00000080; {don't reconnect if there }
- { is a PPC sessClosedErr}
- kAEWantReceipt = nReturnReceipt;
- {client wants return receipt}
-
- {constants for the sendPriority parameter of AESend}
- kAENormalPriority = $00000000; {put event at the back of }
- { event queue}
- kAEHighPriority = nAttnMsg; {put event at the front of }
- { the event queue}
-
- {constant for the returnID parameter of AECreateAppleEvent}
- kAutoGenerateReturnID = -1; {tells Apple Event Manager }
- { to generate a unique }
- { return ID}
-
- {constant for transaction IDs}
- kAnyTransactionID = 0; {the Apple event is not }
- { part of a transaction}
-
- {constants for timeout durations}
- kAEDefaultTimeout = -1; {use default timeout value}
- kNoTimeOut = -2; {never time out}
-
- {constants for the dispatcher parameter of AEResumeTheCurrentEvent}
- kAENoDispatch = 0; {don't redispatch the }
- { Apple event}
- kAEUseStandardDispatch = -1; {redispatch the Apple event }
- { by using its entry in the }
- { Apple event dispatch table}
-
- _______________________________________________________________________________
-
- æKY Apple…Events…Manager…Data…Types
- æC »Apple Events Manager Data Types The Apple Event Manager
- _______________________________________________________________________________
-
- TYPE
- AEEventClass =
- PACKED ARRAY[1..4] OF Char; {event class for a }
- { high-level event}
- AEEventID =
- PACKED ARRAY[1..4] OF Char; {event ID for a high-level }
- { event}
- DescType = ResType; {descriptor type}
-
- AEDesc =
- RECORD {descriptor record}
- descriptorType: DescType; {type of data being passed}
- dataHandle: Handle {handle to data being passed}
- END;
-
- AEKeyword =
- PACKED ARRAY[1..4] OF Char; {keyword for a descriptor}
-
- AEKeyDesc = {keyword-specified }
- { descriptor record}
- RECORD
- descKey: AEKeyword; {keyword}
- descContent: AEDesc; {descriptor record}
- END;
-
- AEAddressDesc = AEDesc; {descriptor containing an }
- { Apple event address}
-
- AEDescList = AEDesc; {list of descriptor records}
-
- AERecord = AEDescList; {list of keyword-specified }
- { descriptor records}
-
- AppleEvent = AERecord; {list of attributes and }
- { parameters necessary for }
- { an Apple event}
- AESendMode = LongInt; {flags that determine how }
- { an Apple event is sent}
-
- AESendPriority = Integer; {send priority of an Apple }
- { event}
-
- AEInteractAllowed = (kAEInteractWithSelf, kAEInteractWithLocal,
- kAEInteractWithAll);
- {what processes may }
- { interact with the user}
-
- AEEventSource = (kAEUnknownSource, kAEDirectCall, kAESameProcess,
- kAELocalProcess, kAERemoteProcess);
- {the source of an Apple }
- { event; the type of the }
- { keyEventSourceAttr }
- { attribute}
-
- AEArrayType = (kAEDataArray, kAEPackedArray, kAEHandleArray,
- kAEDescArray, kAEKeyDescArray);
- {type of an Apple event }
- { array}
-
- AEArrayData =
- RECORD {data for an Apple event }
- { array}
- case AEArrayType OF
- kAEDataArray:
- (AEDataArray: ARRAY[0..0] OF Integer);
- kAEPackedArray:
- (AEPackedArray: PACKED ARRAY[0..0] OF Char);
- kAEHandleArray:
- (AEHandleArray: ARRAY[0..0] OF Handle);
- kAEDescArray:
- (AEDescArray: ARRAY[0..0] OF AEDesc);
- kAEKeyDescArray:
- (AEKeyDescArray: ARRAY[0..0] OF AEKeyDesc);
- END;
-
- AEArrayDataPointer = ^AEArrayData;
-
- EventHandlerProcPtr = ProcPtr; {pointer to an Apple event }
- { handler routine}
-
- IdleProcPtr = ProcPtr; {pointer to an app's }
- { idle function}
-
- EventFilterProcPtr = ProcPtr; {pointer to an app's filter }
- { procedure}
- _______________________________________________________________________________
-
- æKY Apple…Events…Manager…Routines…Summary
- æC »Apple Events Manager Routines Summary The Apple Event Manager
- _______________________________________________________________________________
-
- Creating and Managing the Apple Event Dispatch Tables
-
- FUNCTION AEInstallEventHandler (theAEEventClass: AEEventClass;
- theAEEventID: AEEventID; handler:
- EventHandlerProcPtr; handlerRefcon:
- LongInt; isSysHandler: Boolean) : OSErr;
-
- FUNCTION AEGetEventHandler (theAEEventClass: AEEventClass; theAEEventID:
- AEEventID; VAR handler: EventHandlerProcPtr;
- VAR handlerRefcon: LongInt; isSysHandler:
- Boolean) : OSErr;
-
- FUNCTION AERemoveEventHandler (theAEEventClass: AEEventClass; theAEEventID:
- AEEventID; handler: EventHandlerProcPtr;
- isSysHandler: Boolean) : OSErr;
-
-
- Dispatching Apple Events
-
- FUNCTION AEProcessAppleEvent (theEventRecord: EventRecord) : OSErr;
-
-
- Getting Parameters and Attributes From Apple Events
-
- FUNCTION AEGetParamPtr (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; desiredType: DescType;
- VAR typeCode: DescType; dataPtr: Ptr;
- maximumSize: Size; VAR actualSize: Size) :
- OSErr;
-
- FUNCTION AEGetParamDesc (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; desiredType: DescType; VAR result:
- AEDesc) : OSErr;
-
- FUNCTION AEGetAttributePtr (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; desiredType: DescType; VAR typeCode:
- DescType; dataPtr: Ptr; maximumSize: Size;
- VAR actualSize: Size) : OSErr;
-
- FUNCTION AEGetAttributeDesc (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; desiredType: DescType; VAR result:
- AEDesc) : OSErr;
-
- Counting the Items in Descriptor Lists
-
- FUNCTION AECountItems (theAEDescList: AEDescList; VAR theCount:
- LongInt) : OSErr;
-
- Getting Items From Descriptor Lists
-
- FUNCTION AEGetNthPtr (theAEDescList: AEDescList; index: LongInt;
- desiredType: DescType; VAR theAEKeyword:
- AEKeyword; VAR typeCode: DescType; dataPtr:
- Ptr; maximumSize: Size; VAR actualSize: Size)
- : OSErr;
-
- FUNCTION AEGetNthDesc (theAEDescList: AEDescList; index: LongInt;
- desiredType: DescType; VAR theAEKeyword:
- AEKeyword; VAR result: AEDesc) : OSErr;
-
- FUNCTION AEGetArray (theAEDescList: AEDescList; arrayType:
- AEArrayType; arrayPtr: AEArrayDataPointer;
- maximumSize: Size; VAR itemType: DescType; VAR
- itemSize: Size; VAR itemCount: LongInt) : OSErr;
-
- Getting Data and Keyword-Specified Descriptor Records From AE Records
-
- FUNCTION AEGetKeyPtr (theAERecord: AERecord; theAEKeyword: AEKeyword;
- desiredType: DescType; VAR typeCode: DescType;
- dataPtr: Ptr; maximumSize: Size;
- VAR actualSize: Size) : OSErr;
-
- FUNCTION AEGetKeyDesc (theAERecord: AERecord; theAEKeyword: AEKeyword;
- desiredType: DescType; VAR result: AEDesc)
- : OSErr;
-
-
- Requesting User Interaction
-
- FUNCTION AESetInteractionAllowed (level: AEInteractAllowed) : OSErr;
-
- FUNCTION AEInteractWithUser (timeOutInTicks: LongInt; nmReqPtr:
- QElemPtr; idleProc: IdleProcPtr) : OSErr;
-
- FUNCTION AEGetInteractionAllowed (VAR level: AEInteractAllowed) : OSErr;
-
-
- Requesting More Time to Respond to Apple Events
-
- FUNCTION AEResetTimer (reply: AppleEvent) : OSErr;
-
-
- Suspending and Resuming Apple Event Handling
-
- FUNCTION AESuspendTheCurrentEvent (theAppleEvent: AppleEvent) : OSErr;
-
- FUNCTION AEResumeTheCurrentEvent (theAppleEvent, reply: AppleEvent;
- dispatcher: EventHandlerProcPtr;
- handlerRefcon: LongInt) : OSErr;
-
- FUNCTION AESetTheCurrentEvent (theAppleEvent: AppleEvent) : OSErr;
-
- FUNCTION AEGetTheCurrentEvent (VAR theAppleEvent: AppleEvent): OSErr;
-
-
- Creating Apple Events
-
- FUNCTION AECreateAppleEvent (theAEEventClass: AEEventClass;
- theAEEventID: AEEventID; target:
- AEAddressDesc; returnID: Integer;
- transactionID: LongInt; VAR result:
- AppleEvent) : OSErr;
-
-
- Creating and Duplicating Descriptor Records
-
- FUNCTION AECreateDesc (typeCode: DescType; dataPtr: Ptr; dataSize:
- Size; VAR result: AEDesc) : OSErr;
-
- FUNCTION AEDuplicateDesc (theAEDesc: AEDesc; VAR result: AEDesc)
- : OSErr;
-
-
- Creating Descriptor Lists and AE Records
-
- FUNCTION AECreateList (factoringPtr: Ptr; factoredSize: Size;
- isRecord: Boolean; VAR resultList:
- AEDescList) : OSErr;
-
-
- Adding Items to Descriptor Lists
-
- FUNCTION AEPutPtr (theAEDescList: AEDescList; index: LongInt;
- typeCode: DescType; dataPtr: Ptr; dataSize:
- Size) : OSErr;
-
- FUNCTION AEPutDesc (theAEDescList: AEDescList; index: LongInt;
- theAEDesc: AEDesc) : OSErr;
-
- FUNCTION AEPutArray (theAEDescList: AEDescList; arrayType:
- AEArrayType; arrayPtr: AEArrayDataPointer;
- itemType: DescType; itemSize: Size;
- itemCount: LongInt) : OSErr;
-
-
- Adding Keyword-Specified Descriptor Records to AE Records
-
- FUNCTION AEPutKeyPtr (theAERecord: AERecord; theAEKeyword:
- AEKeyword; typeCode: DescType; dataPtr: Ptr;
- dataSize: Size) : OSErr;
-
- FUNCTION AEPutKeyDesc (theAERecord: AERecord; theAEKeyword:
- AEKeyword; theAEDesc: AEDesc) : OSErr;
-
-
- Adding Parameters and Attributes to Apple Events
-
- FUNCTION AEPutParamPtr (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; typeCode: DescType; dataPtr: Ptr;
- dataSize: Size) : OSErr;
-
- FUNCTION AEPutParamDesc (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; theAEDesc: AEDesc) : OSErr;
-
- FUNCTION AEPutAttributePtr (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; typeCode: DescType; dataPtr: Ptr;
- dataSize: Size) : OSErr;
-
- FUNCTION AEPutAttributeDesc (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; theAEDesc: AEDesc) : OSErr;
-
-
- Sending Apple Events
-
- FUNCTION AESend (theAppleEvent: AppleEvent; VAR reply:
- AppleEvent; sendMode: AESendMode;
- sendPriority: AESendPriority; timeOutInTicks:
- LongInt; idleProc: IdleProcPtr; filterProc:
- EventFilterProcPtr) : OSErr;
-
-
- Getting the Sizes and Descriptor Types of Descriptor Records
-
- FUNCTION AESizeOfNthItem (theAEDescList: AEDescList; index: LongInt; VAR
- typeCode: DescType; VAR dataSize: Size)
- : OSErr;
-
- FUNCTION AESizeOfKeyDesc (theAERecord: AERecord; theAEKeyword:
- AEKeyword; VAR typeCode: DescType;
- VAR dataSize: Size) : OSErr;
-
- FUNCTION AESizeOfParam (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; VAR typeCode: DescType;
- VAR dataSize: Size) : OSErr;
-
- FUNCTION AESizeOfAttribute (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword; VAR typeCode: DescType;
- VAR dataSize: Size) : OSErr;
-
-
- Deleting Descriptor Records
-
- FUNCTION AEDeleteItem (theAEDescList: AEDescList; index: LongInt)
- : OSErr;
-
- FUNCTION AEDeleteKeyDesc (theAERecord: AERecord; theAEKeyword:
- AEKeyword) : OSErr;
-
- FUNCTION AEDeleteParam (theAppleEvent: AppleEvent; theAEKeyword:
- AEKeyword) : OSErr;
-
-
- Deallocating Memory for Descriptor Records
-
- FUNCTION AEDisposeDesc (VAR theAEDesc: AEDesc) : OSErr;
-
-
- Coercing Descriptor Types
-
- FUNCTION AECoercePtr (typeCode: DescType; dataPtr: Ptr; dataSize:
- Size; toType: DescType; VAR result: AEDesc)
- : OSErr;
-
- FUNCTION AECoerceDesc (theAEDesc: AEDesc; toType: DescType;
- VAR result: AEDesc) : OSErr;
-
-
- Creating and Managing the Coercion Handler Tables
-
- FUNCTION AEInstallCoercionHandler (fromType: DescType; toType: DescType;
- handler: ProcPtr; handlerRefcon: LongInt;
- fromTypeIsDesc: Boolean; isSysHandler:
- Boolean) : OSErr;
-
- FUNCTION AEGetCoercionHandler (fromType: DescType; toType: DescType;
- VAR handler: ProcPtr; VAR handlerRefcon:
- LongInt; VAR fromTypeIsDesc: Boolean;
- isSysHandler: Boolean) : OSErr;
-
- FUNCTION AERemoveCoercionHandler (fromType: DescType; toType: DescType;
- handler: ProcPtr; isSysHandler: Boolean)
- : OSErr;
-
-
- Creating and Managing the Special Handler Tables
-
- FUNCTION AEInstallSpecialHandler (functionClass: AEKeyword; handler:
- ProcPtr; isSystemHandler: Boolean)
- : OSErr;
-
- FUNCTION AEGetSpecialHandler (functionClass: AEKeyword; VAR handler:
- ProcPtr; isSystemHandler: Boolean)
- : OSErr;
-
- FUNCTION AERemoveSpecialHandler (functionClass: AEKeyword; handler:
- ProcPtr; isSystemHandler: Boolean)
- : OSErr;
-
-
- Application-Defined Routines
-
- FUNCTION MyEventHandler (theAppleEvent: AppleEvent; reply:
- AppleEvent; handlerRefcon: LongInt) : OSErr;
-
- FUNCTION MyCoercePtr (typeCode: DescType; dataPtr: Ptr; dataSize:
- Size; toType: DescType; handlerRefcon:
- LongInt; VAR result: AEDesc) : OSErr;
-
- FUNCTION MyCoerceDesc (theAEDesc: AEDesc; toType: DescType;
- handlerRefcon: LongInt; VAR result: AEDesc)
- : OSErr;
-
- FUNCTION MyIdleFunction (VAR theEventRecord: EventRecord;
- VAR sleepTime: LongInt; VAR mouseRgn:
- RgnHandle) : Boolean;
-
- FUNCTION MyWaitReplyFilter (VAR theEventRecord: EventRecord;
- transactionID: LongInt; returnID: LongInt;
- sender: AEAddressDesc) : Boolean;
- _______________________________________________________________________________
-
- æKY Apple…Events…Manager…Result…Codes
- æC »Apple Events Manager Result Codes The Apple Event Manager
- _______________________________________________________________________________
-
- noErr 0 No error
- paramErr –50 Parameter error
- (handler pointer is NIL or
- odd)
- memFullErr –108 Not enough room in heap
- zone
- bufferIsSmall –607 Buffer is too small
- noOutstandingHLE –608 No outstanding high-level event
- connectionInvalid –609 Connection is invalid
- errAECoercionFail –1700 Data could not be coerced to
- the requested
-
- type
- errAEDescNotFound –1701 Descriptor record was not found
- errAECorruptData –1702 Data in an Apple event could
- not be read
- errAEWrongDataType –1703 Wrong descriptor type
- errAENotAEDesc –1704 Not a valid descriptor record
- errAEBadListItem –1705 Operation involving a list
- item failed
- errAENewerVersion –1706 Need a newer version of the Apple
- Event
- Manager
- errAENotAppleEvent –1707 Event is not an Apple event
- errAEEventNotHandled –1708 Event wasn’t handled by an Apple event
-
- handler
- errAEReplyNotValid –1709 AEResetTimer was passed an invalid
- reply
- errAEUnknownSendMode –1710 Invalid sending mode was passed
- errAEWaitCanceled –1711 User canceled out of wait loop
- for reply or
- receipt
- errAETimeout –1712 Apple event timed out
- errAENoUserInteraction –1713 No user interaction allowed
- errAENotASpecialFunction –1714 Wrong keyword for a special function
- errAEParamMissed –1715 Handler did not get all required
- parameters
- errAEUnknownAddressType –1716 Unknown Apple event address type
- errAEHandlerNotFound –1717 No handler found for an Apple event or
- a
- coercion
- errAEReplyNotArrived –1718 Reply has not yet arrived
- errAEIllegalIndex –1719 Not a valid list index
- _______________________________________________________________________________
-
- æKY Apple…Events…Manager…Assembly-Language…Information
- æC »Apple Events Manager Assembly-Language Information The Apple Event Manager
- _______________________________________________________________________________
-
- Trap Macros Requiring Routine Selectors
-
- _Pack8
-
-
- Selector Routine
-
- $00 AEInstallSpecialHandler
- $01 AERemoveSpecialHandler
- $02 AECoercePtr
- $03 AECoerceDesc
- $04 AEDisposeDesc
- $05 AEDuplicateDesc
- $06 AECreateList
- $07 AECountItems
- $08 AEPutPtr
- $09 AEPutDesc
- $0A AEGetNthPtr
- $0B AEGetNthDesc
- $0C AEGetArray
- $0D AEPutArray
- $0E AEDeleteItem
- $0F AEPutKeyPtr
- $0F AEPutParamPtr
- $10 AEPutKeyDesc
- $10 AEPutParamDesc
- $11 AEGetParamPtr
- $11 AEGetKeyPtr
- $12 AEGetKeyDesc
- $12 AEGetParamDesc
- $13 AEDeleteKeyDesc
- $13 AEDeleteParam
- $14 AECreateAppleEvent
- $15 AEGetAttributePtr
- $16 AEPutAttributePtr
- $17 AESend
- $18 AEResumeTheCurrentEvent
- $19 AEResetTimer
- $1A AEGetTheCurrentEvent
- $1B AEProcessAppleEvent
- $1C AEInteractWithUser
- $1D AEGetInteractionAllowed
- $1E AESetInteractionAllowed
- $1F AEInstallEventHandler
- $20 AERemoveEventHandler
- $21 AEGetEventHandler
- $22 AEInstallCoercionHandler
- $23 AERemoveCoercionHandler
- $24 AEGetCoercionHandler
- $25 AECreateDesc
- $26 AEGetAttributeDesc
- $27 AEPutAttributeDesc
- $28 AESizeOfAttribute
- $29 AESizeOfParam
- $29 AESizeOfKeyDesc
- $2A AESizeOfNthItem
- $2B AESuspendTheCurrentEvent
- $2C AESetTheCurrentEvent
- $2D AEGetSpecialHandler
-
-
- _______________________________________________________________________________
-
-
- æKY AppleTalkManager
- æC
- _______________________________________________________________________________
-
- APPLETALK MANAGER
- _______________________________________________________________________________
-
- About…Appletalk…Manager…Chapter…Volume…VI
- About…the…Appletalk…Manager…Volume…VI
- Changes…to…the…Appletalk…Manager
- Appletalk…Protocols
- Device…Drivers,connection…Files,…&…the…LAP…Manager
- Using…the…Appletalk…Manager…Volume…VI
- Determining…if…Appletalk…Phase…2…Drivers…Are…Present
- Deciding…Which…Appletalk…Protocol…to…Use
- The….MPP…Driver…Volume…VI
- Getting…Information…About…the….MPP…Driver
- A…New…Nbp…Wildcard…Character
- The…LAP…Manager…Volume…VI
- The…Appletalk…Transition…Queue
- Adding…and…Removing…Appletalk…Transition…Queue…Entries
- Sending…Messages…to…the…Appletalk…Transition…Queue
- How…the…Appletalk…Manager…Calls…Your…Queue…Entry
- Defining…Your…Own…Appletalk…Transition
- The…LAP…Manager…802.2…Protocol
- Attaching…and…Detaching…802.2…Protocol…Handlers
- The….ATP…Driver…Volume…VI
- Canceling…All…Calls…to…the…Atpgetrequest…Function
- Setting…the…Timeout…Value…for…the…Atp…Release…Timer
- The….XPP…Driver…Volume…VI
- Using…the….XPP…Driver…to…Obtain…Information…About…Zones
- Obtaining…Zone…Information
- Appletalk…Data…Stream…Protocol…(adsp)…Volume…VI
- Using…ADSP
- The…ADSP…Connection…Control…Block
- The….DSP…Parameter…Block
- Opening…and…Maintaining…an…ADSP…Connection
- Creating…and…Using…a…Connection…Listener
- Writing…a…User…Routine…for…Connection…Events
- .DSP…Driver…Routines
- Establishing…&…Terminating…an…ADSP…Connection
- Establishing…&…Terminating…an…ADSP…Connection…(cont'd)
- Establishing…&…Terminating…an…ADSP…Connection…Listener
- Maintaining…an…ADSP…Connection
- The….ENET…Driver…Volume…VI
- Providing…Your…Own…Ethernet…Driver
- Changing…the…Ethernet…Hardware…Address
- Opening…the….ENET…Driver
- Using…a…Write-Data…Structure…to…Transmit…Ethernet…Data
- Using…the…Default…Ethernet…Protocol…Handler…to…Read…Data
- Using…Your…Own…Ethernet…Protocol…Handler…to…Read…Data
- How…the….ENET…Driver…Calls…Your…Protocol…Handler
- How…Your…Protocol…Handler…Calls…the….ENET…Driver
- .ENET…Driver…Routines
- Attaching…and…Detaching…an…Ethernet…Protocol…Handler
- Writing…and…Reading…Ethernet…Packets
- Adding…and…Removing…Ethernet…Multicast…Addresses
- Summary…of…the…Appletalk…Manager…Volume…VI
- Appletalk…Manager…Constants
- Appletalk…Manager…Data…Types
- Appletalk…Manager…Routines…Summary
- Appletalk…Manager…Global…Variable
- Appletalk…Manager…Result…Codes
- Appletalk…Manager…Assembly-language…Information
-
- About…The…AppleTalkManager…Chapter
- AppleTalk…Protocols
- AppleTalk…Transaction…Protocol
- About…the…AppleTalk…Manager
- Calling…the…AppleTalk…Manager…from…Pascal
- New…AppleTalk…Manager…Pascal…Interface
- Picking…a…Node…Address…in…the…Server…Range
- Sending…Packets…to…One’s…Own…Node
- ATP…Driver…Changes
- Name…Binding…Protocol…Changes
- Variable…Resources
- Calling…the…AppleTalk…Manager…from…Assembly…Language
- Extended…Protocol…Package…Driver
- Calling…the….XPP…Driver
- Protocol…Handlers…and…Socket…Listeners
- Summary…of…the…AppleTalk…Manager
-
- _______________________________________________________________________________
-
-
-
- æKY About…Appletalk…Manager…Chapter…Volume…VI
- æC »About Appletalk Manager Chapter Volume VI AppleTalk Manager
- _______________________________________________________________________________
-
- AppleTalk® is a communications network system including personal computer
- workstations, computers acting as file servers and print servers, printers, and
- a variety of types of communications hardware and software. The AppleTalk
- Manager provides an interface to this communications network system for
- applications running on Macintosh® computers. This chapter describes changes to
- the AppleTalk Manager introduced since the publication of Inside Macintosh ,
- Volume V, and included with system software version 7.0. This chapter
- supplements the information in the AppleTalk Manager chapters of Inside
- Macintosh, Volumes II and V.
-
- This chapter describes
-
- • new routines for the .MPP, .ATP, and .XPP device drivers
-
- • a new wildcard character for use with the Name-Binding Protocol
-
- • a new operating-system queue, called the AppleTalk Transition Queue
-
- • a new set of operating-system utilities, collectively called the LAP
- Manager
-
- • the application interface routines provided by a new AppleTalk protocol,
- the
- AppleTalk Data Stream Protocol (ADSP)
-
- • the .ENET driver and the routines your application can use to control this
- driver
-
- Together with the AppleTalk Manager chapters of Volumes II and V, this chapter
- describes the routines that your application can use to send and receive
- information within an AppleTalk network system. Because the AppleTalk network
- system includes both hardware and software—and because the software includes not
- only the AppleTalk Manager but also file servers, print servers, internet
- routers, drivers for circuit cards, and so forth—the information in Inside
- Macintosh constitutes only a small part of the body of literature documenting
- AppleTalk.
-
- For a detailed description of AppleTalk protocols, see Inside AppleTalk . For a
- complete description of the LAP Manager, EtherTalk®, and alternate AppleTalk
- connections, see the AppleTalk Connections Programmer’s Guide . To learn how to
- install and operate an AppleTalk internet, see the AppleTalk Internet Router
- Administrator’s Guide and the AppleTalk Phase 2 Introduction and Upgrade Guide
- . For an introduction to the hardware and software of an entire AppleTalk
- network, see Understanding Computer Networks and the AppleTalk Network System
- Overview . For information on designing circuit cards and device drivers for
- Macintosh computers, see Designing Cards and Drivers for the Macintosh Family .
-
- The changes to AppleTalk other than ADSP and the LAP Manager are collectively
- referred to as AppleTalk Phase 2. (When necessary for purposes of
- differentiation, the previous version of AppleTalk is referred to in this
- chapter as AppleTalk Phase 1.) The Phase 2 versions of the AppleTalk drivers are
- included as part of system software version 7.0 and can be installed on any
- Macintosh computer other than the Macintosh 128K, Macintosh 512K, Macintosh 512K
- enhanced, and Macintosh XL computers. If you want to provide AppleTalk Phase 2
- drivers with your product, you must obtain a license from Apple® Software
- Licensing.
-
- _______________________________________________________________________________
-
- æKY About…the…Appletalk…Manager…Volume…VI
- æC »About the Appletalk Manager Volume VI AppleTalk Manager
- _______________________________________________________________________________
-
- The AppleTalk Manager includes a number of protocols that are implemented in
- various device drivers. The AppleTalk Manager also includes the LAP Manager
- (which interfaces the AppleTalk link access protocols to the higher-level
- AppleTalk protocols), and hardware device drivers for specific data links.
- Software that supports AppleTalk data links is contained in files of type
- 'adev', referred to as AppleTalk connection files . This section lists the new
- features of AppleTalk, describes the organization of the AppleTalk Manager, and
- briefly discusses what each component of the AppleTalk Manager does.
-
- _______________________________________________________________________________
-
- æKY Changes…to…the…Appletalk…Manager
- æC »Changes to the Appletalk Manager AppleTalk Manager
- _______________________________________________________________________________
-
- The AppleTalk features that are new or improved include
-
- • a new .MPP driver function that returns information about the .MPP driver
- (see “Getting Information About the .MPP Driver,” later in this chapter)
-
- • a new Name-Binding Protocol (NBP) wildcard character that can substitute
- for
- one or more characters in AppleTalk names (see “A New NBP Wildcard
- Character”)
-
- • the LAP Manager, a set of operating-system utilities that provide a
- standard
- interface between the AppleTalk protocols and the data links used by
- AppleTalk, such as LocalTalk®, EtherTalk, and TokenTalk® (see “The LAP
- Manager”)
-
- • the AppleTalk Transition Queue, an operating-system queue that can notify
- your application each time an AppleTalk driver is opened or closed or each
- time certain other transitions occur (see “The AppleTalk Transition
- Queue”)
-
- • an implementation of parts of the IEEE 802.2 protocol, which allows you to
- attach and detach your own protocol handlers for EtherTalk data packets
- (see
- “The LAP Manager 802.2 Protocol”)
-
- • new .ATP driver functions that allow you to set a value for the .ATP
- release
- timer and to cancel all pending asynchronous calls to the the
- ATPGetRequest
- function for a specific socket (see “The .ATP Driver”)
-
- • new .XPP driver functions that provide information from ZIP about zones
- (see
- “The .XPP Driver”)
-
- • improvements to the AppleTalk protocols that allow a single network, other
- than LocalTalk, to contain more than one zone (see “Using the .XPP Driver
- to
- Obtain Zone Information”)
-
- • the AppleTalk Data Stream Protocol (ADSP), which provides full-duplex data
- stream communications for use by applications (see “AppleTalk Data Stream
- Protocol”)
-
- • the .ENET driver, an Ethernet driver for the EtherTalk NB card that is
- manufactured by Apple Computer, Inc. (see “The .ENET Driver”)
- _______________________________________________________________________________
-
- æKY Appletalk…Protocols
- æC »Appletalk Protocols AppleTalk Manager
- _______________________________________________________________________________
-
- The AppleTalk Manager includes the following protocols:
-
- • LocalTalk Link Access Protocol (LLAP)
-
- • EtherTalk Link Access Protocol (ELAP)
-
- • TokenTalk Link Access Protocol (TLAP)
-
- • Datagram Delivery Protocol (DDP)
-
- • Routing Table Maintenance Protocol (RTMP)
-
- • AppleTalk Transaction Protocol (ATP)
-
- • Name-Binding Protocol (NBP)
-
- • AppleTalk Echo Protocol (AEP)
-
- • Zone Information Protocol (ZIP)
-
- • AppleTalk Session Protocol (ASP)
-
- • AppleTalk Data Stream Protocol (ADSP)
-
- • AppleTalk Filing Protocol (AFP)
-
- The LocalTalk Link Access Protocol, EtherTalk Link Access Protocol, TokenTalk
- Link Access Protocol, and other link access protocols provide interfaces between
- the AppleTalk Manager and the different types of data link hardware used by
- AppleTalk.
-
- Note: The LocalTalk Link Access Protocol (LLAP) was originally called the
- AppleTalk Link Access Protocol (ALAP). With the addition of the EtherTalk
- Link
- Access Protocol (ELAP) and other link access protocols, this protocol was
- renamed
- to indicate the specific data link it supports.
-
- Figure 32-1 shows the relationships among the various AppleTalk protocols. A
- line going from a protocol to another protocol above or below it in the figure
- indicates that the upper protocol is a client of the lower protocol; that is,
- the upper protocol uses services provided by the lower protocol in order to
- carry out some functions.
-
- ¿ Figure 32-1 AppleTalk protocols ø
-
- Note: The various AppleTalk protocols are sets of rules, not computer
- programs,
- and so can be implemented in many different ways on many different systems.
- All of the AppleTalk protocol functions that you can address or control from
- a
- Macintosh application are implemented as Macintosh device drivers or
- managers. Many other features of these protocols are implemented in software
- located only on internet routers that are not used to run general
- applications.
- Some parts of protocols are implemented by server software such as file
- servers
- and print servers. Therefore, when this chapter refers to a protocol as
- “doing” or
- “controlling” something, you should understand the statement to mean that
- some program that implements the protocol actually carries out the operation.
-
- As shown in Figure 32-1, a link access protocol controls the access of the node
- to the network hardware and makes it possible for many nodes to share the same
- communications hardware. Each link access protocol assigns a node ID to the node
- and decodes the node addresses of messages it receives. A link access protocol
- provides node-to-node delivery of data packets. Examples of link access
- protocols include the LocalTalk Link Access Protocol, the EtherTalk Link Access
- Protocol, and the TokenTalk Link Access Protocol.
-
- Whereas earlier implementations of AppleTalk were restricted to one 16-bit
- network number per network (that is, one network number for all nodes connected
- with no intervening routers) and 254 nodes per network number, AppleTalk Phase 2
- allows more than one network number for each network (other than LocalTalk,
- which is still limited to one network number per network). A network of a type
- that allows more than one network number is known as an extended network. Each
- node in an extended network must now be specified by both its 16-bit network
- number and its 8-bit node ID. In principle, each network (other than LocalTalk)
- can now have over 16 million (224) nodes. In any specific implementation, the
- hardware or software might limit the network to fewer nodes.
-
- The Datagram Delivery Protocol (DDP) provides socket-to-socket delivery of data
- packets within an AppleTalk internet. The address of a DDP packet includes the
- socket number, node ID, and network number. Application interface routines for
- DDP are described in “Datagram Delivery Protocol” in the AppleTalk Manager
- chapter of Volume II.
-
- The Routing Table Maintenance Protocol (RTMP) is used by routers on an AppleTalk
- internet to determine how to forward a data packet to the network number to
- which it is addressed. The RTMP implementation on a router maintains a table,
- called a routing table, that specifies the shortest path to each possible
- destination network number. The AppleTalk protocol software in a workstation
- (that is, a node other than a router) contains only a small part of RTMP, called
- the RTMP stub, that DDP uses to determine the network number (or range of
- network numbers) of the network cable to which the node is connected and to
- determine the network number and node ID of one router on that network cable.
- There is no application interface to the RTMP stub.
-
- The AppleTalk Transaction Protocol (ATP) provides reliable delivery of data by
- retransmitting any data packets that are lost. ATP also ensures that data
- packets are delivered in the correct sequence. ATP is a transaction-based
- protocol, meaning that one socket client transmits a request for some action and
- the other socket client carries out the action and transmits a response.
- Although—as you can see from Figure 32-1—the AppleTalk Manager provides
- high-level protocols that are clients of ATP, many applications use ATP directly
- to transmit data over an AppleTalk internet. The application interface to ATP is
- described in the AppleTalk Manager chapter of Volume II. There are some
- enhancements to ATP in AppleTalk Phase 2, described in “The .ATP Driver” later
- in this chapter.
-
- The Name-Binding Protocol (NBP) maintains a table that contains the internet
- address and name of each entity in the node that is visible to other entities on
- the internet (that is, each entity that has registered a name with NBP). The
- internet address includes the socket number, node ID, and network number. The
- name consists of three fields: the object, type, and zone. The object and type
- are assigned by the entity itself and can be anything the user or application
- assigns. A zone is a logical grouping of a subset of the nodes on the internet.
- The zone field of the name is the zone in which the node resides.
-
- NBP also allows its clients to obtain the internet address of any
- network-visible entity in the internet by providing its name. NBP maps this name
- to an internet address, thus providing the link between the user-supplied name
- for an entity and the internet address that is used by DDP to send and receive
- data packets. The application interface to NBP is described in the AppleTalk
- Manager chapter of Volume II. There is one enhancement to NBP in AppleTalk Phase
- 2, described in “A New NBP Wildcard Character” later in this chapter.
-
- The AppleTalk Echo Protocol (AEP) listens for special packets sent by other
- nodes and, when it receives such a packet, echoes it back to the sender. AEP is
- used by some clients of DDP to determine whether another node (known to have
- AEP) can be accessed over the internet, and to determine how long it takes a
- packet to reach another node. There is no application interface to AEP.
-
- The Zone Information Protocol (ZIP) maintains a table in each router, called the
- zone information table, that lists the relationships between zone names and
- networks. In AppleTalk Phase 2, a single network number can be associated with
- more than one zone name, or a single zone name can be associated with more than
- one network. You can use .XPP driver routines to obtain information from ZIP.
- These routines are discussed in “Using the .XPP Driver to Obtain Information
- About Zones” later in this chapter.
-
- The AppleTalk Session Protocol (ASP) sets up and maintains sessions between a
- workstation and a server. A session consists of a logical (as opposed to
- physical) connection between two entities on the internet. ASP is a
- nonsymmetrical protocol; that is, only one of the two entities involved in the
- session (the workstation) can send commands. The other entity (the server) is
- restricted to responding to the commands. ASP is used by the AppleTalk Filing
- Protocol, for example, to allow a user to manipulate files on a file server. As
- long as the session is open, the workstation can request directory information,
- change filenames, and so forth. The file server must respond to the
- workstation’s commands and cannot initiate any actions on its own. ASP is
- discussed in the AppleTalk Manager chapter of Volume V.
-
- The AppleTalk Data Stream Protocol (ADSP) appears to its clients to maintain an
- open pipeline between two entities on the internet. Either entity can write a
- stream of bytes to the pipeline or read data bytes from the pipeline. ADSP is a
- symmetrical protocol; that is, the two clients at either end of the connection
- are equal and can perform exactly the same operations. ADSP is especially useful
- for exchanging information between two equal entities, as in a telephone
- communications network, or as required by a terminal emulation program for
- sending or receiving a continuous stream of data. Because ADSP, like all other
- high-level AppleTalk protocols is a client of DDP, the data is actually sent as
- data packets. This allows ADSP to correct transmission errors in a way that
- would not be possible for a true data stream connection. Thus, ADSP retains many
- of the advantages of a transaction-based protocol while providing to its clients
- a full-duplex data stream. ADSP is discussed in the sections “Using ADSP” and
- “.DSP Driver Routines” later in this chapter.
-
- The AppleTalk Filing Protocol (AFP) provides an interface between an application
- and a file server. AFP is a client of ASP and is used to access AppleShare® file
- servers on Macintosh computer workstations. When the user opens a session with
- an AppleShare file server over an internet, it appears to any application
- running on the workstation that uses File Manager routines as if the files on
- the file server were located on a disk drive connected to the workstation. The
- application interface to AFP is described in the AppleTalk Manager chapter of
- Volume V.
-
- _______________________________________________________________________________
-
- æKY Device…Drivers,connection…Files,…&…the…LAP…Manager
- æC »Device Drivers,connection Files, & the LAP Manager AppleTalk Manager
- _______________________________________________________________________________
-
- A protocol is only a set of rules, not a computer program. The various AppleTalk
- protocols are implemented as Macintosh device drivers, including
-
- • the .MPP driver, which implements LLAP, DDP, the RTMP stub, NBP, and AEP
-
- • the .ATP driver, which implements ATP
-
- • the .XPP driver, which implements ASP and the workstation portions of ZIP
- and AFP
-
- • the .DSP driver, which implements ADSP
-
- • the .ENET driver, which implements an interface to the Ethernet data link
-
- A Macintosh computer on an AppleTalk network can also include one or more
- AppleTalk connection files. An AppleTalk connection file has file type 'adev'
- and contains a link access protocol implementation for a data link (ELAP for
- EtherTalk, for example). The LAP Manager makes it possible for the user to
- select among AppleTalk connection files by using the Network control panel to
- specify which network is to be used for the node’s AppleTalk connection. The
- AppleTalk connection file and LAP Manager work together with the Network control
- panel (Network 'cdev') file. When the user selects a connection from the Network
- control panel, the LAP Manager routes AppleTalk communications through the
- selected link access protocol and hence through the selected hardware.
-
- The AppleTalk device drivers, LAP Manager, and AppleTalk connection files are
- shown in Figure 32-2. As you can see from the figure, each device driver
- implements one or more AppleTalk protocols.
-
- ¿ Figure 32-2 AppleTalk device drivers ø
-
- Figure 32-3 shows the interfaces between a general application on a Macintosh
- computer being used as an AppleTalk workstation and the AppleTalk protocols, the
- LAP Manager, and the Ethernet hardware device driver. The lines connecting the
- application to the various components of AppleTalk indicate which components
- have application interfaces. As discussed in the preceding section, “AppleTalk
- Protocols,” each application interface is described, at least in part, in this
- or another volume of Inside Macintosh .
-
- ¿ Figure 32-3 AppleTalk application interfaces ø
-
-
- _______________________________________________________________________________
-
- æKY Using…the…Appletalk…Manager…Volume…VI
- æC »Using the Appletalk Manager Volume VI AppleTalk Manager
- _______________________________________________________________________________
-
- This section describes how to determine whether AppleTalk Phase 2 drivers are
- present and gives some advice on how to select the AppleTalk protocol that best
- serves your purposes. This section also describes how to use the features added
- to AppleTalk with Phase 2 and provides programming examples of the use of the
- .DSP driver and several other new AppleTalk features.
-
- _______________________________________________________________________________
-
- æKY Determining…if…Appletalk…Phase…2…Drivers…Are…Present
- æC »Determining if Appletalk Phase 2 Drivers Are Present AppleTalk Manager
- _______________________________________________________________________________
-
- Once the .MPP driver has been loaded into memory, you can use the Gestalt
- function with the gestaltAppleTalkVersion selector to check the version of
- AppleTalk. The Gestalt function returns the version of the .MPP driver. If the
- version is equal to or greater than 53, then the .MPP driver supports AppleTalk
- Phase 2, and you can assume the other Phase 2 drivers are present.
-
- Alternatively, you can call the SysEnvirons function as described in the
- Compatibility Guidelines chapter of Volume V. If the atDrvrVersNum field of the
- SysEnvRec data structure returned by this function is equal to or greater than
- 53, then the .MPP driver supports AppleTalk Phase 2.
-
- The ExtendedBit flag returned by the pGetAppleTalkInfo function is TRUE if the
- node is connected to an extended AppleTalk network. (The ExtendedBit flag is bit
- 15 of the configuration parameter returned by this function.) Note that the
- presence of the AppleTalk Phase 2 drivers does not of itself indicate that the
- node is connected to an extended network.
-
- _______________________________________________________________________________
-
- æKY Deciding…Which…Appletalk…Protocol…to…Use
- æC »Deciding Which Appletalk Protocol to Use AppleTalk Manager
- _______________________________________________________________________________
-
- AppleTalk offers a variety of communications protocols at a variety of levels.
- Your choice of protocol or protocols to use depends primarily on your needs and
- can be influenced by your familiarity with network communications in general.
-
- You can write your own protocol handlers and call the low-level AppleTalk device
- drivers directly. However, if you are not a communications expert and have no
- desire to design your own network protocols, you should probably use one of
- three AppleTalk protocols for sending and receiving data over the AppleTalk
- internet: the AppleTalk Transaction Protocol (ATP), the AppleTalk Session
- Protocol (ASP), or the AppleTalk Data Stream Protocol (ADSP).
-
- ATP is a lower-level protocol than ASP or ADSP. You cannot use ATP to establish
- a session and keep it open; rather, you request data from another socket client
- or send a response (up to eight packets of data) from your socket to another
- socket client that has requested data. You should use ATP if you want only to
- send a small amount of data and do not need the overhead required to maintain an
- open connection. ATP is described in the AppleTalk Manager chapters of Volume II
- and Volume V.
-
- ASP is designed to support a session between a server and one or more
- workstations. It is an asymmetrical protocol: all exchanges are initiated by a
- workstation and responded to by a server. The server cannot initiate an exchange
- of data except to send to a workstation an attention message that directs the
- workstation to request data from the server. An application running on a
- workstation must make calls to ASP to communicate with any server that uses ASP.
- If you want to develop a new type of asymmetrical, transaction-oriented server,
- you should consider using ASP to implement it. ASP is described in the AppleTalk
- Manager chapter of Volume V.
-
- ADSP is a symmetrical protocol that you can use to establish and maintain a
- connection between two equal entities (a peer-to-peer connection). Either end of
- an ADSP connection can send data at any time. Although ADSP is a client of DDP
- and therefore sends and receives data in packets (as do ATP and ASP), to an
- application using ADSP the data appears to be sent and received as a continuous
- stream. In addition to the duplex data stream maintained by an ADSP session,
- ADSP allows either end of a connection to send an attention message to the other
- end. You can use ADSP to establish two-way communication between computers, such
- as an interoffice party line or a terminal emulation program. If you want to
- develop an application that requires two-way communication, you should consider
- using ADSP to implement it. ADSP is described in “Using ADSP” later in this
- chapter.
-
- _______________________________________________________________________________
-
- æKY The….MPP…Driver…Volume…VI
- æC »The .MPP Driver Volume VI AppleTalk Manager
- _______________________________________________________________________________
-
- Within the AppleTalk Manager, the .MPP driver implements the LocalTalk Link
- Access Protocol (LLAP), the Datagram Delivery Protocol (DDP), the Routing Table
- Maintenance Protocol (RTMP) stub, the Name-Binding Protocol (NBP), and the
- AppleTalk Echo Protocol (AEP). The AppleTalk Phase 2 version of the .MPP driver
- includes a new function that returns information about the .MPP driver,
- functions that send messages to routines in the AppleTalk Transition Queue, and
- a new wildcard character for NBP.
-
- _______________________________________________________________________________
-
- æKY Getting…Information…About…the….MPP…Driver
- æC »Getting Information About the .MPP Driver AppleTalk Manager
- _______________________________________________________________________________
-
- You can use the PGetAppleTalkInfo function to obtain information about the .MPP
- driver. The PGetAppleTalkInfo function returns
-
- • a pointer to the .MPP global variables
-
- • a pointer to the .MPP driver’s device control entry (DCE) data structure
-
- • configuration flags that indicate the status of certain conditions that are
- set at
- startup
-
- • a value (the selfSend flag) that indicates whether the node can send
- packets to
- itself
-
- • the range of network numbers for the network to which the node is attached
-
- • the 8-bit node ID and 16-bit network number of the node
-
- • the 8-bit node ID and 16-bit network number of the last router from which
- the
- node has heard
-
- • the maximum capacities of the .MPP driver, such as the maximum number of
- protocol handlers and the maximum number of static sockets allowed by this
- driver
-
- • a pointer to the registered names queue
-
- • the address of the node on the underlying data link (for example, the
- Ethernet
- hardware address)
-
- • the node’s zone name
-
- The data link address (for example, the Ethernet hardware address) and the zone
- name are returned only for extended networks; that is, network types that allow
- more than one network number per network. You must allocate memory for and
- provide pointers to the data buffers into which the PGetAppleTalkInfo function
- returns the data link address and zone name. You use the laLength parameter to
- specify the length of the data link address you want returned; the function
- returns the actual length of the data in the laLength parameter and returns the
- data in the buffer you provide.
-
- Note: Always use the PGetAppleTalkInfo function to obtain information about
- the .MPP driver. You can no longer rely on the validity of the global
- variables
- described in the AppleTalk Manager chapter of Volume II.
-
- FUNCTION PGetAppleTalkInfo (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always
- PGetAppleTalkInfo
- Æ 28 version word version of function
- ¨ 30 varsPtr long pointer to .MPP
- globals
- ¨ 34 dcePtr long pointer to DCE for
- .MPP
- ¨ 38 portID word port number
- ¨ 40 configuration long configuration flags
- ¨ 44 selfSend word nonzero if self-send
- is enabled
- ¨ 46 netLo word low value of the
- network range
- ¨ 48 netHi word high value of the
- network range
- ¨ 50 ourAddr long local 24-bit AppleTalk
- address
- ¨ 54 routerAddr long 24-bit address of router
- ¨ 58 numOfPHs word max number of protocol
- handlers
- ¨ 60 numOfSkts word max number of static
- sockets
- ¨ 62 numNBPEs word max concurrent NBP requests
- ¨ 64 ntQueue long pointer to registered
- names queue
- ´ 68 laLength word length in bytes of
- data link address
-
-
-
-
- Æ 70 linkAddr long pointer to data link
- address buffer
-
-
-
-
- Æ 74 zoneName long pointer to zone name
- buffer
-
- The PGetAppleTalkInfo function returns information about the .MPP driver. If the
- node on which your program is running happens also to be running AppleTalk
- Internet Router software in the background, more than one set of .MPP global
- variables may be in RAM. To make sure you are obtaining information about the
- .MPP driver that handles application software, always use the PGetAppleTalkInfo
- function rather than the Device Manager’s PBControl function. If you are using
- assembly language or want to use the PBControl function, you must use a device
- driver reference number of –10 for the .MPP driver.
-
- Fields
-
- ioResult The result of the function. When you
- execute the function
- asynchronously, the function sets
- this parameter to 1 and
- returns a function result of noErr
- as soon as the function
- begins execution. When the function
- completes execution,
- it sets the ioResult parameter to
- the actual result code.
-
- csCode Routine selector, automatically set by the
- MPW® interface.
- Always equal to PGetAppleTalkInfo
- for this function.
-
- version The version number of the PGetAppleTalkInfo
- function
- you are calling. For version number
- 53 of the .MPP driver,
- this number is always 1.
-
- varsPtr A pointer to the .MPP global variables.
- This parameter is
- reserved for the use of Apple
- Computer, Inc.; you cannot
- rely on the validity of the
- variables pointed to by this
- parameter.
-
- dcePtr A pointer to the device control entry
- (DCE) data structure
- for the .MPP driver. The DCE is
- described in the Device
- Manager chapters of Volumes II and V.
-
- portID The port number for the .MPP driver. The
- port number is
- always 0 unless you are requesting
- information for an .MPP
- driver being used by a router.
-
- configuration A 32-bit long word of configuration flags. The
- following
- flags are currently defined:
-
- Bit Flag
- Description
- 31 SrvAdrBit TRUE (1)
- if the routine that opened
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 30 RouterBit TRUE
- (1) if an AppleTalk Internet
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 15 ExtendedBit TRUE (1)
- if the node is on an
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 7 BadZoneHintBit TRUE (1) if
- the zone name of the
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 6 OneZoneBit TRUE (1)
- if only one zone is
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- selfSend The ability of a node to send packets to
- itself. This feature is
- enabled when this parameter is
- nonzero. Use the
- PSetSelfSend function, described in
- the AppleTalk Manager
- chapter of Volume V, to enable or
- disable this feature.
-
- netLo The low value of the range of network
- numbers on the
- local cable. Only extended networks
- can have a range of
- network numbers. For a nonextended
- network, this
- parameter returns the network
- number.
-
- netHi The high value of the range of network
- numbers on the
- local cable. Only extended networks
- can have a range of
- network numbers. For a nonextended
- network, this
- parameter returns the network
- number.
-
- ourAddr The 24-bit AppleTalk network address of the
- node you are
- on. The least significant byte of
- the long word is the node
- ID. The middle 16 bits are the
- network number. The most
- significant byte of the long word
- is reserved for use by
- Apple Computer, Inc.
-
- routerAddr The 24-bit AppleTalk network address of the
- last router
- from which your node heard traffic.
- The least significant
- byte of the long word is the node
- ID. The middle 16 bits are
- the network number. The most
- significant byte of the long
- word is reserved for use by Apple
- Computer, Inc. You
- should always use this address when
- you want to
- communicate with a router.
-
- numOfPHs The maximum number of protocol handlers that
- this
- .MPP driver allows.
-
- numOfSkts The maximum number of statically assigned
- sockets that
- this .MPP driver allows.
- Statically assigned sockets are
- described in Inside AppleTalk.
-
- numNBPEs The maximum number of concurrent requests to NBP
- that
- this .MPP driver allows.
-
- ntQueue A pointer to the first entry in the names
- table for the local
- node. You can use NBP routines to
- look up and register
- names in the names table. The
- names table is described in
- “Name-Binding Protocol” in the
- AppleTalk Manager
- chapter of Volume II.
-
- laLength The number of bytes of the data link address
- that the
- function should place in the buffer
- pointed to by the
- LinkAddr parameter. You use this
- parameter when you
- call the PGetAppleTalkInfo function
- on a node on an
- extended network. If you request
- more bytes than the total
- number of bytes in the address,
- then the function returns
- in the laLength parameter the
- actual number of bytes it
- placed in the buffer. If the
- address is longer than the size of
- the buffer, then the
- PGetAppleTalkInfo function fills
- the
- buffer and returns in the laLength
- parameter the actual
- length of the address, not the
- number of bytes returned.
- The function does not return an
- error when the buffer is
- too large or too small for the
- address. A value of 6 bytes for
- laLength is sufficient for most
- purposes.
-
- linkAddr A pointer to a buffer for the data link
- address returned for
- extended networks only. You use the
- laLength parameter
- to specify the number of bytes of
- the address that you want
- placed in this buffer. You must
- allocate a buffer large
- enough to hold the number of bytes
- you specify. Specify
- NIL for this parameter if you do
- not want the function to
- provide a data link address.
-
- zoneName A pointer to a buffer into which the
- PGetAppleTalkInfo
- function places the local node’s
- zone name. You must
- allocate a buffer of at least 33
- bytes to hold this data, or you
- must specify NIL for the ZoneName
- parameter if you do
- not want to obtain the zone name.
- This field is returned
- only if the node is on an extended
- network.
-
- Result codes
- noErr 0 No error
- paramErr –50 Version number is too high
-
- _______________________________________________________________________________
-
- æKY A…New…Nbp…Wildcard…Character
- æC »A New Nbp Wildcard Character AppleTalk Manager
- _______________________________________________________________________________
-
- The Name-Binding Protocol (NBP) allows the use of certain wildcard characters in
- AppleTalk names when you call the PLookupName function. NBP now supports the
- following wildcard characters:
-
- NBP wildcard characters
-
- = All possible values. The equal sign (=)
- can be used alone
- instead of a name in the object or type
- fields.
-
- * This zone. The asterisk (*) can be used
- in place of the name of
- the zone to which this node belongs.
-
- ≈ Any or no characters in this position.
- The double tilde (≈) can
- be used to obtain matches for object or
- type fields. For
- example, pa≈l matches pal, paul, paper
- ball, and so forth. You
- can use only one double tilde in any
- string. Press Option-x to
- type the double tilde character on a
- Macintosh keyboard. If
- you use the double tilde alone, it has
- the same meaning as
- the equal sign (=). Note that any node
- not running AppleTalk
- Phase 2 drivers will not recognize this
- character.
-
- _______________________________________________________________________________
-
- æKY The…LAP…Manager…Volume…VI
- æC »The LAP Manager Volume VI AppleTalk Manager
- _______________________________________________________________________________
-
- The LAP Manager is a set of operating-system utilities that provide a standard
- interface between the AppleTalk protocols and the various link access protocols,
- such as LocalTalk (LLAP), EtherTalk (ELAP), and TokenTalk (TLAP). Because the
- LAP Manager is running even when the .MPP driver is not open, the LAP Manager
- also maintains the AppleTalk Transition Queue. In addition, the LAP Manager
- contains protocol handlers for certain types of 802.2 packets.
-
- This section describes the AppleTalk Transition Queue and the LAP Manager 802.2
- protocol handler, tells you how to add or remove an AppleTalk Transition Queue
- entry, and describes how to attach or detach your own 802.2 protocol handler. In
- addition to the LAP Manager features described here, you can use the LAP Manager
- to interface new data links to AppleTalk. For more information about the LAP
- Manager, see the AppleTalk Connections Programmer’s Guide .
-
- _______________________________________________________________________________
-
- æKY The…Appletalk…Transition…Queue
- æC »The Appletalk Transition Queue AppleTalk Manager
- _______________________________________________________________________________
-
- At any given time there might be two or more applications running that use
- AppleTalk. If one of these applications opens the AppleTalk drivers, the other
- AppleTalk applications are affected. If the Operating System closes the
- AppleTalk drivers, all AppleTalk applications are affected. To ensure that your
- application is not adversely affected by such an event, your application can
- place an entry in the AppleTalk Transition Queue. The LAP Manager sends a
- message to each entry in the AppleTalk Transition Queue each time the Operating
- System or any routine
-
- • opens the .MPP driver
-
- • closes the .MPP driver
-
- • indicates that it intends to close the .MPP driver
-
- • cancels its intention to close the .MPP driver
-
- • defines its own AppleTalk event and calls the AppleTalk Transition Queue to
- inform it that such an event occurred
-
- Each of these events is referred to as an AppleTalk transition.
-
- Because the .MPP driver is not necessarily open when the AppleTalk Transition
- Queue must be called, the LAP Manager maintains the queue. Each entry in the
- AppleTalk Transition Queue is defined by the ATQentry data type.
-
- TYPE ATQentry =
- RECORD
- qLink: ATQentryPtr; {next queue entry}
- qType: Integer; {reserved}
- CallAddr: ProcPtr {pointer to your routine}
- END;
-
- When you want to add an entry to the AppleTalk Transition Queue, you must create
- an ATQentry data structure and give the LAP Manager a pointer to it. The qLink
- field is a pointer to the next queue entry. You should set this field to NIL;
- the LAP Manager fills it in when an application adds another entry to the queue.
- The qType field is reserved to maintain consistency with other operating-system
- queues. The CallAddr field is a pointer to a routine that you provide, as
- described in “How the AppleTalk Manager Calls Your AppleTalk Transition Queue
- Entry” later in this chapter.
-
- Because you provide the memory for the AppleTalk Transition Queue entry, you can
- add as many fields to the end of the entry as you wish for your own purposes.
- Whenever your routine is called, the caller provides you with a pointer to the
- queue entry so that you can have access to the information you stored at the end
- of your queue entry.
-
- There are four LAP Manager functions you can use that are related to the
- AppleTalk Transition Queue:
-
- • The LAPAddATQ function adds an entry to the AppleTalk Transition Queue.
- This function is described in the following section, “Adding and Removing
- AppleTalk Transition Queue Entries.”
-
- • The LAPRmvATQ function removes an entry from the AppleTalk Transition
- Queue. This function is described in the following section, “Adding and
- Removing AppleTalk Transition Queue Entries.”
-
- • The ATEvent procedure calls all the entries in the AppleTalk Transition
- Queue
- with an AppleTalk transition event of your own definition. This function
- is
- described in the section “Defining Your Own AppleTalk Transition,” later
- in
- this chapter.
-
- • The ATPreFlightEvent function calls all the entries in the AppleTalk
- Transition Queue with an AppleTalk transition event of your own
- definition
- and gives each entry the opportunity to respond. This function is
- described in
- the section “Defining Your Own AppleTalk Transition,” later in this
- chapter.
-
- _______________________________________________________________________________
-
- æKY Adding…and…Removing…Appletalk…Transition…Queue…Entries
- æC »Adding and Removing Appletalk Transition Queue Entries AppleTalk Manager
- _______________________________________________________________________________
-
- You can use LAP Manager routines to add or remove an entry to the AppleTalk
- Transition Queue.
-
- _____________________________________________________
- Assembly-language note: From assembly language, you add and
- remove AppleTalk Transition Queue entries by placing a routine
- selector in the D0 register, placing a pointer to your AppleTalk
- Transition Queue entry in the A0 register, and executing a JSR
- instruction to an offset past the start of the LAP Manager. The start
-
- of the LAP Manager is contained in the global variable LAPMgrPtr
- ($B18). The offset to the LAP Manager routines is given by the
- constant LAPMgrCall (2).
-
- Here is assembly-language code that adds or removes AppleTalk
- Tranisition Queue entries:
-
- LAPMgrPtr EQU $B18 ;entry point for LAP Manager
- LAPMgrCall EQU 2 ;offset to LAP Manager routines
- ATQEntry EQU * ;pointer to ATQ entry
- ...
-
- MOVEQ #RSel,D0 ;place routine selector
- ; in D0 (23 to add an entry, 24
- ; to remove one)
- MOVE.L LAPMgrPtr,An ;put pointer to LAP Mgr in An
- MOVE.L ATQEntry,A0 ;put ATQ entry in A0
- JSR LAPMgrCall(An) ;jump to start of LAP Mgr
- ; routines
- _____________________________________________________
-
- FUNCTION LAPAddATQ (theATQEntry: ATQEntryPtr): OSErr;
-
- __________________________________________________
- On entry D0: 23
- A0: pointer to AppleTalk
- Transition Queue entry
- On exit D0: result code
- __________________________________________________
-
- The LAPAddATQ function adds an entry to the AppleTalk Transition Queue. The
- parameter theATQEntry is a pointer to an ATQentry data structure. The CallAddr
- field of the data structure holds a pointer to the routine that AppleTalk calls
- for any AppleTalk transition event. The ATQentry data structure is described in
- the preceding section, “The AppleTalk Transition Queue.”
-
- Result codes
- noErr 0 No error
-
- FUNCTION LAPRmvATQ (theATQEntry: ATQEntryPtr): OSErr;
-
- _________________________________________________
-
- On entry D0: 24
- A0: pointer to AppleTalk Transition
- Queue entry
- On exit D0: result code
- _________________________________________________
-
- The LAPRmvATQ function removes an entry from the AppleTalk Transition Queue. The
- parameter theATQEntry is a pointer to an ATQentry data structure.
-
- Note: You must not call the LAPRmvATQ function at interrupt time or through
- a callback routine. This restriction is to prevent any routine from removing
- an
- entry from the AppleTalk Transition Queue while another routine is in the
- process of adding or removing an entry.
-
- Result codes
- noErr 0 No error
- qErr –1 Queue element not found
- _______________________________________________________________________________
-
- æKY Sending…Messages…to…the…Appletalk…Transition…Queue
- æC »Sending Messages to the Appletalk Transition Queue AppleTalk Manager
- _______________________________________________________________________________
-
- Whereas it is unlikely that opening the .MPP driver will adversely affect
- another program, an application should never close the .MPP driver, because
- another program might be using it. Under certain circumstances, however, the
- system might close the .MPP driver. The system uses the .MPP driver’s
- PATalkClosePrep function to send a permission-to-close transition to each
- routine in the AppleTalk Transition Queue. This transition indicates that the
- system intends to close the .MPP driver so that each routine in the queue has
- the opportunity to deny permission to do so.
-
- When the system calls the PATalkClosePrep function, any routine in the AppleTalk
- Transition Queue that wishes to deny permission to close the .MPP driver may
- return a pointer to a Pascal string. The Pascal string should be the name of the
- application that placed the entry in the queue. If any routine in the AppleTalk
- Transition Queue denies permission to close the .MPP driver, the PATalkClosePrep
- function returns the result code closeErr.
-
- If any routine denies permission to close the .MPP driver, the AppleTalk Manager
- sends a cancel-close transition to every routine in the AppleTalk Transition
- Queue that previously received the permission-to-close transition. The caller of
- the PATalkClosePrep function may display a dialog box informing the user that
- another application is using the .MPP driver and showing the name (if any)
- returned by the AppleTalk Transition Queue routine. The dialog box gives the
- user the option of canceling the request to close AppleTalk or of closing
- AppleTalk anyway.
-
- If the user chooses to close AppleTalk despite the fact that an application is
- using it, the system calls the MPPClose function. AppleTalk then calls each
- application in the AppleTalk Transition Queue, this time informing each one that
- AppleTalk is about to close. In this case, your AppleTalk Transition Queue
- routine must prepare for the imminent closing of AppleTalk; it cannot deny
- permission to the MPPClose function.
-
- FUNCTION PATalkClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- Æ 26 csCode word always PATalkClosePrep
- ¨ 28 appName long pointer to name of application
- that
- denies
- request
-
- The PATalkClosePrep function calls each routine listed in the AppleTalk
- Transition Queue to request permission to close the .MPP driver.
-
- If a routine in the AppleTalk Transition Queue denies permission to close the
- .MPP driver, that routine can return a pointer to a Pascal string. The Pascal
- string should contain the name of the application that placed the entry in the
- AppleTalk Transition Queue. The PATalkClosePrep function returns that pointer in
- the appName field. The function also returns the result code closeErr,
- indicating that the calling routine has been denied permission to close the .MPP
- driver. The routine that called PATalkClosePrep can then display a dialog box
- telling the user the name of the application that is currently using AppleTalk
- and asking whether to close AppleTalk anyway.
-
- The csCode parameter is a routine selector; it is always equal to
- PATalkClosePrep for this function.
-
- Result codes
- noErr 0 No error
- closeErr –24 Permission to close .MPP driver was denied
-
- _______________________________________________________________________________
-
- æKY How…the…Appletalk…Manager…Calls…Your…Queue…Entry
- æC »How the Appletalk Manager Calls Your Queue Entry AppleTalk Manager
- _______________________________________________________________________________
-
- When you have used the LAPAddATQ function to add an entry to the AppleTalk
- Transition Queue, the AppleTalk Manager calls your entry when any of the
- following events occurs:
-
- • A routine opens the .MPP driver.
-
- • A routine closes the .MPP driver.
-
- • A routine calls the PATalkClosePrep function.
-
- • One of the routines in the AppleTalk Transition Queue denies permission for
- the routine that called the PATalkClosePrep function to close AppleTalk.
-
- • An application calls the ATEvent or ATPreFlightEvent routines to send its
- own
- AppleTalk transition event to the entries in the AppleTalk Transition
- Queue.
-
- When the AppleTalk Manager calls your AppleTalk Transition Queue routine, the
- stack looks like this:
-
- Chart 32-1 Contents of the stack on a call to an ATQ routine ø
-
- The first item on the stack (after the return address) is a routine selector.
- There is one routine selector for each type of transition. The open,
- prepare-to-close, permission-to-close, and cancel-close transitions each have a
- single-digit routine selector; all other routine selectors for AppleTalk
- transition events are 4-character codes. Codes starting with an uppercase letter
- (A through Z) are reserved for use by developers. All other codes are reserved
- for use by Apple Computer, Inc.
-
- Routine selector Transition
-
- $00 00 00 00 .MPP driver opened
- $00 00 00 02 .MPP driver about to
- close
- $00 00 00 03 PATalkClosePrep
- function has been called
- $00 00 00 04 Closing of .MPP driver
- has been canceled
- $41 xx xx xx —$5A xx xx xx Reserved for use by developers
- all others Reserved for use by
- Apple Computer
-
- You can use the following constants for the standard AppleTalk transitions:
-
- CONST ATTransOpen = 0; {open transition}
- ATTransClose = 2; {prepare-to-close transition}
- ATTransClosePrep = 3; {permission-to-close
- transition}
- ATTransCancelClose = 4; {cancel-close transition}
-
- The second item passed to your routine on the stack is a pointer to your
- routine’s entry in the AppleTalk Transition Queue. You can use this pointer to
- get access to any fields at the end of the queue entry that you allocated for
- your own use. The last item passed to your routine on the stack is a parameter
- whose meaning depends on the type of transition.
-
- The interface between the AppleTalk Transition Queue and your routine follows
- these conventions: Your routine must preserve all registers except D0, D1, D2,
- A0, and A1; all parameters are passed on the stack as long words. Because your
- routine might be called at interrupt time, your routine must not make any direct
- or indirect calls to the Memory Manager and can’t depend on handles to unlocked
- blocks being valid. If you want to use any of your application’s global
- variables, you must save the contents of the A5 register before using the
- variables, and you must restore the A5 register before your routine terminates.
- These restrictions do not apply to the open transition or the prepare-to-close
- transition.
-
- Note: It is important that you return a 0 in the D0 register whenever you
- receive
- a transition event routine selector that you do not recognize or do not
- choose to
- handle. Returning a nonzero value in the D0 register might cause the system
- to
- cancel an attempt to close AppleTalk, for example, or might be misinterpreted
- in
- some other way.
-
-
- Open Transition
-
- When an application calls the MPPOpen function, the AppleTalk Manager first
- attempts to open the .MPP driver. If the .MPP driver is already open, the
- AppleTalk Manager does not call the AppleTalk Transition Queue. If the AppleTalk
- Manager successfully opens the .MPP driver, it then calls every routine listed
- in the AppleTalk Transition Queue with an open transition.
-
- The third item on the stack for an open transition is a pointer to the start of
- the Device Manager extended parameter block used by the routine that opened the
- .MPP driver. This pointer is provided for your information only; you must not
- change any of the fields in this parameter block.
-
- Your AppleTalk Transition Queue routine can perform any tasks you wish in
- response to the notification that the .MPP driver has been opened, such as using
- the Name-Binding Protocol (NBP) to register a name on the internet. Return 0 in
- the D0 register to indicate that your routine executed with no error.
-
-
- Prepare-to-Close Transistion
-
- When any routine calls the MPPClose function to close the .MPP driver, the
- AppleTalk Manager calls every routine listed in the AppleTalk Transition Queue
- before the .MPP driver closes. If the .MPP driver is already closed when a
- routine calls the MPPClose function, the AppleTalk Manager does not call the
- routines in the AppleTalk Transition Queue.
-
- When the AppleTalk Manager calls your routine for a prepare-to-close transition,
- the third item on the stack is a NIL pointer.
-
- Your routine can perform any tasks you wish to prepare for the imminent closing
- of AppleTalk, such as ending a session with a remote terminal and informing the
- user that the connection is being closed. You must return control to the
- AppleTalk Manager as quickly as possible. Return 0 in the D0 register to
- indicate that your routine executed with no error.
-
- Note: When the AppleTalk Manager calls your routine with a prepare-to-close
- transition (that is, a routine selector of ATTransClose), you cannot prevent
- the
- .MPP driver from closing.
-
-
- Permission-to-Close Transition
-
- When a routine calls the PATalkClosePrep function to inform the AppleTalk
- Manager that it wants to close the .MPP driver, the AppleTalk Manager calls
- every routine listed in the AppleTalk Transition Queue to request permission to
- close the .MPP driver.
-
- When the AppleTalk Manager calls your routine to request permission to close the
- .MPP driver, the third parameter on the stack is a pointer to a 4-byte buffer.
- If you intend to deny the request to close AppleTalk, you should place in the
- buffer a pointer to a Pascal string containing the name of your application. The
- PATalkClosePrep function returns this pointer. The routine that called the
- PATalkClosePrep function can then display a dialog box telling the user the name
- of the application that is currently using AppleTalk.
-
- Your routine can return either a function result of 0 in the D0 register,
- indicating that it accepts the request to close, or a 1 in the D0 register,
- indicating that it denies the request to close. Note that the Operating System
- might elect to close AppleTalk anyway; for example, if the user grants
- permission to close in response to a dialog box.
-
- Because the AppleTalk Manager calls your routine again (with the routine
- selector set to ATTransClose) before the .MPP driver actually closes, it is not
- necessary for your routine to do anything other than grant or deny permission in
- response to being called for a permission-to-close transition. However, you
- might want to prohibit the users from opening new sessions or establishing new
- connections while you are waiting for the .MPP driver to close.
-
-
- Cancel-Close Transition
-
- When any routine in the AppleTalk Transition Queue denies permission for the
- .MPP driver to close, the AppleTalk Manager calls each routine listed in the
- AppleTalk Transition Queue that has already received the permission-to-close
- transition to inform it that the request to close the .MPP driver has been
- canceled.
-
- When the AppleTalk Manager calls your AppleTalk Transition Queue routine for a
- cancel-close transition, the third item on the stack is a NIL pointer.
-
- If your routine performed any tasks to prepare for the closing of AppleTalk, it
- should reverse their effects when it is called with the routine selector set to
- ATTransCancelClose. Return 0 in the D0 register to indicate that your routine
- executed with no error.
-
-
- Developer-Defined Transitions
-
- Any AppleTalk transition event code that begins with an uppercase letter (that
- is, any value in the range $41 00 00 00 through $5A FF FF FF) indicates a
- developer-defined event. You can use such events to send messages to your own
- entries in the AppleTalk Transition Queue, or you can define events and make
- them public for others to use. Because you cannot tell how the originator of
- such an event might interpret a nonzero function result, you must always return
- 0 in the D0 register for any AppleTalk transition event code that you do not
- recognize.
-
- When you return a nonzero result code for certain developer-defined transitions,
- the AppleTalk Manager may call your AppleTalk Transition Queue routine a second
- time with a cancel transition analogous to the cancel-close transition.
-
-
- _______________________________________________________________________________
-
- æKY Defining…Your…Own…Appletalk…Transition
- æC »Defining Your Own Appletalk Transition AppleTalk Manager
- _______________________________________________________________________________
-
- You can define your own AppleTalk transition to have any meaning you choose. For
- example, you might want to call every routine in the AppleTalk Transition Queue
- each time you open an AppleTalk Data Stream Protocol (ADSP) connection.
-
- You can use either the ATEvent procedure or the ATPreFlightEvent function to
- notify all of the routines in the AppleTalk Transition Queue that your AppleTalk
- transition has occurred. Whereas the ATEvent procedure only calls the routines
- in the queue with a transition event, the ATPreFlightEvent function also allows
- each routine in the AppleTalk Transition Queue to return a result code and other
- information to your calling routine.
-
- Note: You can call the ATEvent and ATPreFlightEvent routines only at
- virtual-memory safe time. See the Memory Manager chapter in this volume for
- information on virtual memory.
-
- PROCEDURE ATEvent (event: LongInt; infoPtr: Ptr);
-
- The ATEvent procedure calls all of the routines in the AppleTalk Transition
- Queue with the AppleTalk transition event code you specify in the event
- parameter. The AppleTalk transition event code can be any 4-character string
- that starts with an uppercase letter; that is, any value in the range $41 00 00
- 00 through $5A FF FF FF. You can use the infoPtr parameter to point to any
- information that you want to make available to the AppleTalk Transition Queue
- routines; for an ADSP-open transition, for example, you might pass a pointer to
- the parameter block used by the dspOpen routine. If you do not want to pass any
- information to the AppleTalk Transition Queue routines, set the infoPtr
- parameter to NIL.
-
- FUNCTION ATPreFlightEvent (event,cancel: LongInt; infoPtr: Ptr) : OSErr;
-
- The ATPreFlightEvent function calls all of the routines in the AppleTalk
- Transition Queue with the AppleTalk transition event code you specify in the
- event parameter. If any routine in the AppleTalk Transition Queue returns a
- nonzero function result, the ATPreFlightEvent function calls each of the
- routines that it has already called, this time with the AppleTalk transition
- event code you specify in the cancel parameter. The AppleTalk transition event
- codes can be any 4-character strings that start with an uppercase letter; that
- is, any values in the range $41 00 00 00 through $5A FF FF FF. You can use the
- infoPtr parameter to point to any information that you want to make available to
- the AppleTalk Transition Queue routines. If you do not want to pass any
- information to the AppleTalk Transition Queue routines, set the infoPtr
- parameter to NIL.
-
- Result codes
- noErr 0 No error, or unrecognized event code
-
- Note: AppleTalk transitions defined by developers might return other result
- codes.
-
-
- _______________________________________________________________________________
-
- æKY The…LAP…Manager…802.2…Protocol
- æC »The LAP Manager 802.2 Protocol AppleTalk Manager
- _______________________________________________________________________________
-
- The Institute of Electrical and Electronics Engineers (IEEE) has defined a
- series of communications protocols for use on a variety of networks. At the
- physical level, these protocols include the 802.3 CSMA/CD protocol, the 802.4
- token bus protocol, and the 802.5 token ring protocol. At the data link level,
- you access these protocols through another IEEE protocol, the 802.2 protocol.
- The AppleTalk LAP Manager includes two routines that allow you to attach and
- detach protocol handlers for 802.2 Type 1 data packets: the L802Attach and
- L802Detach routines. You can write an application that reads 802.2 Type 1 data
- packets and use the L802Attach routine to install your application as a client
- of the LAP Manager. The ANSI/IEEE standards for the 802 protocols are published
- by the IEEE.
-
- The first 14 bytes of a packet sent or received by the .ENET driver constitute
- the header. The first 12 bytes consist of the destination and source data-link
- addresses, such as the Ethernet hardware addresses. If the value of the last 2
- bytes in the header is greater than 1500, then the .ENET driver treats that
- field as an Ethernet protocol type discriminator. See “The .ENET Driver,” later
- in this chapter, for more information on Ethernet protocols. If the value of the
- last 2 bytes in the header is less than or equal to 1500, then the packet is an
- 802.3 protocol packet and this field indicates the length of the 802.3 data. The
- .ENET driver passes all 802.3 packets to the LAP Manager.
-
- The LAP Manager receives the entire 802.3 packet from the .ENET driver. The
- first 3 bytes of the 802.3 data constitute the header for the 802.2 protocol.
- The first byte of the 802.2 header is known as the destination service access
- point (DSAP). If the DSAP field is equal to $AA, then the first 5 bytes of the
- 802.2 data constitute a protocol discriminator known as the subnetwork access
- protocol (SNAP) type. If the SNAP type field is $00000080F3, indicating the
- AppleTalk Address Resolution Protocol (AARP), then the next 4 bytes of the 802.2
- data constitute a third type field, the AARP packet type. AARP is discussed in
- Inside AppleTalk.
-
- The first packet header in Figure 32-4, for example, indicates an Ethernet
- packet containing AppleTalk Phase 1 data. The .ENET driver would deliver this
- packet to the AppleTalk Phase 1 protocol handler.
-
- By contrast, the second data packet header in the figure indicates an 802.3
- packet containing AppleTalk Phase 2 data. The .ENET driver would deliver this
- packet to the AppleTalk Phase 2 LAP Manager.
-
- Similarly, the third data packet header in Figure 32-4 indicates an 802.3 packet
- to be delivered to the Phase 2 EtherTalk AARP handler:
-
- ¿ Figure 32-4 AppleTalk Ethernet packet formats ø
-
- When you call the L802Attach routine, you provide a pointer to your protocol
- handler, the reference number of the .ENET driver, and a pointer to a string
- containing one or more type fields. The type fields indicate the DSAP value and
- any other protocol type fields (such as the SNAP type and the AARP type). The
- LAP Manager delivers to your protocol handler any 802.2 data packets that have
- the protocol type you specify.
-
- _______________________________________________________________________________
-
- æKY Attaching…and…Detaching…802.2…Protocol…Handlers
- æC »Attaching and Detaching 802.2 Protocol Handlers AppleTalk Manager
- _______________________________________________________________________________
-
- You can attach to the LAP Manager your own protocol handler for 802.2 protocols.
- The LAP Manager has permanent handlers for certain types of EtherTalk packets.
- You cannot replace or override the permanent LAP Manager protocol handlers.
-
- There are no high-level interfaces for the LAP Manager 802.2 protocol routines.
- You call these routines from assembly language by placing a routine selector in
- the D0 register and executing a JSR instruction to an offset 2 bytes past the
- start of the LAP Manager. The start of the LAP Manager is contained in the
- global variable LAPMgrPtr ($B18).
-
- Before you call these routines, you must place the reference number of the .ENET
- driver in the D2 register and a pointer to the protocol type specification in
- the A1 register. Before you call the L802Attach routine, you must also place a
- pointer to your protocol handler in the A0 register. Both routines return a
- nonzero value in the D0 register if there is an error.
-
- Listing 32-1 shows how to call a LAP Manager L802.2 routine from assembly
- language.
-
- ¿ Listing 32-1 Calling a LAP Manager L802.2 routine from assembly language
-
- LAPMgrPtr EQU $B18 ;entry point for LAP Manager
- LAPMgrCall EQU 2 ;offset to LAP Manager routines
- L802Entry EQU * ;L802 routine entry
- ...
-
- MOVEQ #RSel,D0 ;place routine selector
- ; in D0
- MOVEQ #refNum,D2 ;place driver reference number
- ; in D2
- MOVE.L PHndlrPtr,A0 ;put pointer to protocol
- ; handler in A0 (L802Attach
- ; only)
- MOVE.L PSpecPtr,A1 ;put pointer to protocol
- ; specification in A1)
- MOVE.L LAPMgrPtr,An ;put pointer to LAP Mgr in An
- JSR LAPMgrCall(An) ;jump to start of LAP Mgr
- ; routines
-
-
- L802Attach
- _______________________________________________
- On entry D0: 21
- D2: reference number of .ENET
- driver
- A0: pointer to your protocol
- handler
- A1: pointer to protocol
- specification
-
- On exit D0: nonzero if error
- _______________________________________________
-
- The L802Attach routine attaches to the LAP Manager a protocol handler for a
- specific IEEE 802.2 protocol type.
-
- Before calling this routine, you must put the value 21 in the D0 register and
- the reference number of the .ENET driver in the D2 register. The .ENET driver
- reference number is returned by the OpenSlot function. If you are not using the
- .ENET driver or a driver that uses the same interface as the .ENET driver, you
- cannot use the L802Attach routine.
-
- You must put a pointer to your protocol handler in the A0 register and a pointer
- to the protocol-type specification for this protocol handler in the A1 register.
- The protocol-type specification consists of one or more protocol-type fields,
- each preceded by a length byte. The LAP Manager reads the protocol-type fields
- in the 802.2 data packet header to determine to which protocol handler (if any)
- to deliver the packet. The first type field in your protocol specification is
- the 1-byte DSAP. If the DSAP type field is equal to $AA, then the protocol-type
- specification must contain a second type field, the 5-byte SNAP type. If the
- SNAP type field is $00000080F3, indicating the AppleTalk Address Resolution
- Protocol (AARP), then the protocol-type specification must contain a third type
- field, the 4byte AARP protocol type. Terminate the list of protocol-type fields
- with a byte of zeros.
-
- The following protocol-type specification, for example, is for the permanent LAP
- Manager protocol handler for an 802.3 packet containing AppleTalk data. The
- .ENET driver would deliver this packet to the AppleTalk Phase 2 LAP Manager. The
- first byte, $01, is the length byte for the first protocol-type field (the DSAP
- type field), $AA. The third byte, $05, is the length byte for the next
- protocol-type field, the SNAP. The final byte ($00) terminates the type
- specification.
-
- 01 AA 05 08 00 07 80 9B 00
-
- The following protocol-type specification is for the permanent LAP Manager
- protocol handler for an 802.3 packet to be delivered to the EtherTalk AARP
- handler. Notice that the SNAP field is followed by an additional type field, the
- AARP protocol type.
-
- 01 AA 05 00 00 00 80 F3 04 00 01 80 9B 00
-
- Note: The DSAP value of $AA is reserved for use with protocol-type
- specifications that include a SNAP field. The SNAP value of $08 00 07 80 9B
- is
- reserved for AppleTalk data. The SNAP value of $00 00 00 80 F3 is reserved
- for
- AARP data. The AARP protocol type value of $00 01 80 9B is reserved for
- EtherTalk AARP packets.
-
- See the ANSI/IEEE standard 802.2 for more information about 802.2 protocols, and
- see Inside AppleTalk for more information about AARP.
-
-
- L802Detach
- ________________________________________________
- On entry D0: 22
- D2: reference number of .ENET
- driver
- A1: pointer to protocol
- specification
-
- On exit D0: nonzero if error
- ________________________________________________
-
- The L802Detach routine detaches from the LAP Manager a protocol handler for a
- specific IEEE 802.2 protocol type.
-
- Before calling this routine, you must put the value 22 in the D0 register and
- the reference number of the .ENET driver in the D2 register. The .ENET driver
- reference number is returned by the OpenSlot function. If you are not using the
- .ENET driver or a driver that uses the same interface as the .ENET driver, you
- cannot use the L802Detach routine.
-
- You must put a pointer to the protocol-type specification for this protocol
- handler in the A1 register. You must specify exactly the same protocol type as
- you specified for the L802Attach routine when you attached the protocol handler.
-
- _______________________________________________________________________________
-
- æKY The….ATP…Driver…Volume…VI
- æC »The .ATP Driver Volume VI AppleTalk Manager
- _______________________________________________________________________________
-
- AppleTalk Phase 2 includes two changes to the .ATP driver: you can now cancel
- all calls to the ATPGetRequest function that are pending execution, and you can
- now set the release timer for AppleTalk Transaction Protocol (ATP) exactly-once
- (XO) service to one of five different values.
-
- _______________________________________________________________________________
-
- æKY Canceling…All…Calls…to…the…Atpgetrequest…Function
- æC »Canceling All Calls to the Atpgetrequest Function AppleTalk Manager
- _______________________________________________________________________________
-
- The ATPGetRequest function sets a socket to receive a request sent by another
- socket. If you call the ATPGetRequest function asynchronously, you can have
- several calls to the function simultaneously pending execution. The
- ATPKillAllGetReq function cancels all calls to the ATPGetRequest function
- pending for a specific socket without closing the socket.
-
- FUNCTION ATPKillAllGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- Æ 26 csCode word always ATPKillAllGetReq
- Æ 28 atpSocket byte socket for which to cancel all
- calls
- to
- ATPGetRequest
-
- The ATPKillAllGetReq function cancels all pending asynchronous calls to the
- ATPGetRequest function for the socket you specify with the atpSocket parameter.
- The ATPKillAllGetReq function also calls the completion routine for each call to
- the ATPGetRequest function with the result code reqAborted (–1105) in the D0
- register.
-
- Unlike the ATPCloseSocket function, the ATPKillAllGetReq function does not close
- the socket. You should call the ATPKillAllGetReq function before closing a
- socket. The csCode parameter is a routine selector, automatically set by the MPW
- interface. It is always equal to ATPKillAllGetReq for this function.
-
- Result codes
- noErr 0 No error
- cbNotFound –1102 Control block not found; no pending asynchronous
- calls
- _______________________________________________________________________________
-
- æKY Setting…the…Timeout…Value…for…the…Atp…Release…Timer
- æC »Setting the Timeout Value for the Atp Release Timer AppleTalk Manager
- _______________________________________________________________________________
-
- The .ATP driver maintains a timer, called the release timer , for each call to
- the PSendResponse function that is part of an exactly-once (XO) transaction. If
- the timer expires before the transaction is complete (that is, before the socket
- receives the transaction release packet), the driver completes the PSendResponse
- function. Before AppleTalk Phase 2, the release timer was always set to 30
- seconds. To set the other connection end’s release timer to another value, set
- bit 2 of the atpFlags field in the parameter block for the PSendRequest or the
- PNSendRequest function and add a new byte field to the parameter block at offset
- 50—the TRelTime field. (The PSendRequest and PNSendRequest functions use the
- SendRequestParm variant of the ATP parameter block.) Here is the ATP parameter
- block for the PSendRequest and PNSendRequest functions:
-
- TYPE ATPParamBlock =
- PACKED RECORD {extended parameter block }
- { for PSendRequest and }
- { PNSendRequest}
- qLink: QElemPtr; {next queue entry}
- qType: Integer; {queue type}
- ioTrap: Integer; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OsErr; {result code}
- userData: LongInt; {ATP user bytes}
- reqTID: Integer; {request transaction ID}
- ioRefNum: Integer; {driver reference number}
- csCode: Integer; {primary command code}
- atpSocket: Byte; {currBitMap or socket number}
- atpFlags: Byte; {control information - set bit 2 }
- { for extended parameter block}
- addrBlock: AddrBlock; {source socket address}
- reqLength: Integer; {request size in bytes}
- reqPointer: Ptr; {pointer to request data}
- bdsPointer: Ptr; {pointer to response Buffer }
- { Data Structure}
- numOfBuffs: Byte; {number of responses expected}
- timeOutVal: Byte; {timeout interval}
- numOfResps: Byte; {number of responses }
- { actually received}
- retryCount: Byte; {number of retries}
- intBuff: Integer; {used internally for PNSendRequest}
- TRelTime: Byte {release timer setting}
- end;
-
- The lower three bits of the TRelTime field indicate the time to which the
- release timer is to be set, as follows:
-
- TRelTime field Setting of release timer
-
- 000 30 seconds
- 001 1 minute
- 010 2 minutes
- 011 4 minutes
- 100 8 minutes
-
- Note: The nodes at both ends of the ATP connection must be running AppleTalk
- Phase 2 drivers for this feature to work.
-
- XO service, the release timer, and the SendRequest function are described in the
- AppleTalk Manager chapter of Volume II. The ATP parameter block and the
- PNSendRequest function are described in the AppleTalk Manager chapter of Volume
- V.
-
- _______________________________________________________________________________
-
- æKY The….XPP…Driver…Volume…VI
- æC »The .XPP Driver Volume VI AppleTalk Manager
- _______________________________________________________________________________
-
- The .XPP driver provides these functions that return information about zones:
-
- • The GetMyZone function returns the AppleTalk zone name of the node on
- which your application is running. This function works for both extended
- and
- nonextended networks.
-
- • The GetLocalZones function returns a list of zone names on the network that
- includes the node on which your application is running. This function
- works
- for extended networks only.
-
- • The GetZoneList function returns a complete list of zones on the internet.
-
- Note: Before the AppleTalk Phase 2 version of the .XPP driver, you had to
- use
- AppleTalk Transaction Protocol (ATP) to obtain zone information and request
- it
- directly from a router. The Zone Information Protocol (ZIP) functions
- provided
- by the new version of the .XPP driver make it much easier for you to obtain
- this
- information. To ensure compatibility with future versions of AppleTalk, you
- should always use the functions described in this section to obtain zone
- information.
-
- For the GetMyZone, GetLocalZones, and GetZoneList functions, the .XPP driver
- uses the xCallParam variant to the XPP parameter block.
-
- TYPE XPPParamBlock =
- PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: Integer; {queue type}
- ioTrap: Integer; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OsErr; {result code}
- cmdResult: LongInt; {command result}
- ioVRefNum: Integer; {volume reference number}
- ioRefNum: Integer; {driver reference number}
- csCode: Integer; {primary command code}
- CASE XPPPrmBlkType OF
- xCallParam
- xppSubCode: Integer; {secondary command code}
- xppTimeOut: Byte; {timeout period for .XPP}
- xppRetry: Byte; {retry count}
- filler1: Integer; {reserved}
- zipBuffPtr: Ptr; {returned zone names}
- zipNumZones: Integer; {number of zones returned}
- zipLastFlag: Byte; {nonzero when all zone }
- { names have been returned}
- filler2 Byte; {reserved}
- zipInfoField: packed array[1..70] of Byte
- {reserved for use by .XPP}
- END;
- XPPParmBlkPtr = ^XPPParamBlock;
-
- As for all other AppleTalk Manager preferred interface functions, the MPW
- interface calls the Device Manager PBControl function to implement these ZIP
- protocol functions. The qLink, qType, ioTrap, ioCmdAddr, and ioVRefNum fields
- are filled in by the Device Manager; your application should not have to set or
- read these fields. The ioResult field returns the result of the function. If you
- call the function asynchronously, the Device Manager sets this field to 1 as
- soon as you call the function, and it changes the field to the actual result
- code when the function completes execution. The ioCompletion field is a pointer
- to a completion routine that you can provide; the Device Manager calls your
- completion routine when it completes execution of the PBControl function. If you
- are not providing a completion routine, specify NIL for this field.
-
- The value of the ioRefNum field is returned by the OpenDriver function; you must
- provide this value in each call to an .XPP driver routine. The csCode and
- xppSubCode fields specify the command to be executed; the MPW Pascal interface
- fills in these fields for you.The .XPP zone information functions do not use the
- cmdResult field.
-
- _______________________________________________________________________________
-
- æKY Using…the….XPP…Driver…to…Obtain…Information…About…Zones
- æC »Using the .XPP Driver to Obtain Information About Zones AppleTalk Manager
- _______________________________________________________________________________
-
- The Zone Information Protocol (ZIP) obtains the zone information by using the
- AppleTalk Transaction Protocol (ATP) to send an information request to a router.
- The xppTimeOut field specifies the amount of time, in seconds, that the .ATP
- driver should wait between attempts to obtain the data. The xppRetry field
- specifies the number of times the .ATP driver should attempt to obtain the data
- before returning the reqFailed (request failed) result code.
-
- The zipBuffPtr field is a pointer to a data buffer that you must allocate. This
- buffer must be 578 bytes for the GetZoneList and GetLocalZones functions and 33
- bytes for the GetMyZone function. ZIP returns the zone names (as a packed array
- of packed Pascal strings) into this buffer. The zipNumZones field returns the
- actual number of zone names that ZIP placed in the buffer. You must set the
- zipLastFlag field to 0 (FALSE) before you execute the GetZoneList or
- GetLocalZones functions. If the zipLastFlag parameter is still 0 when the
- command has completed execution, then ZIP is waiting to return more zone names.
- In this case you must empty the buffer (or allocate a new one) and call the
- GetZoneList or GetLocalZones function again immediately. When there are no more
- zone names to return, ZIP sets the zipLastFlag field to a nonzero (TRUE) value.
-
- The zipInfoField field is a 70-byte data buffer that you must allocate for use
- by the .XPP driver. The first time you call any of these functions, you must set
- the first word of this field to 0. You must not change any values in this field
- subsequently.
-
- Listing 32-2 illustrates the use of the GetZoneList function. The GetLocalZones
- function operates in exactly the same fashion.
-
- ¿ Listing 32-2 Using the GetZoneList function
-
- PROCEDURE doGetZoneList;
-
- VAR
- myXPPPB: XPPParamBlock; {.XPP parameter block}
- myErr: OSErr;
-
- BEGIN
- WITH myXPPPB DO
- BEGIN
- xppTimeOut := 3; {timeout period for .XPP}
- xppRetry := 4; {retry count}
- zipBuffPtr := NewPtr(578); {zone names returned here}
- zipLastFlag := 0; {set to 0 the first time through}
- zipInfoField[1] := 0;
- zipInfoField[2] := 0; {first word is 0 the first }
- { time through}
- END;
- myErr := noErr;
-
- {Check the zipNumZones field to determine how many zone names }
- { have been returned in the buffer. Append the zone names to the }
- { end of your own buffer before returning to read more zone names.}
-
- {loop to get all of the zone names}
- WHILE (myXPPPB.zipLastFlag = 0) & (myErr = noErr) DO
- BEGIN
- myErr := GetZoneList(@myXPPPB, FALSE);
- EmptyDataBuf(@myXPPPB); {your routine to empty }
- { data buffer}
- END;
- YourZIPProc(@myXPPPB); {your routine to process names}
- IF myErr <> noErr THEN DoError(myErr);
- {there's an error}
- DisposPtr(myXPPPB.zipBuffPtr); {give space back}
- END;
-
- Listing 32-3 illustrates the use of the GetMyZone function.
-
- ¿ Listing 32-3 Using the GetMyZone function
-
- PROCEDURE doGetMyZone;
-
- VAR
- myXPPPB: XPPParamBlock; {.XPP parameter block}
- myZoneName: ARRAY[1..33] OF CHAR;
- myErr: OSErr;
-
- BEGIN
- WITH myXPPPB DO
- BEGIN
- xppTimeOut := 3; {timeout period for .XPP}
- xppRetry := 4; {retry count}
- zipBuffPtr := @myZoneName; {zone name returned here}
- zipInfoField[1] := 0;
- zipInfoField[2] := 0; {first word is 0 the first }
- { time through}
- END;
- myErr := GetMyZone(@myXPPPB, FALSE);
- IF myErr <> noErr THEN DoError(myErr);
- {there's an error}
- END;
- _______________________________________________________________________________
-
- æKY Obtaining…Zone…Information
- æC »Obtaining Zone Information AppleTalk Manager
- _______________________________________________________________________________
-
- The .XPP driver provides three functions that obtain information about zones.
- All three functions use the Zone Information Protocol (ZIP) to return the names
- of zones.
-
- _________________________________________________
-
- Assembly-language note: The .XPP driver functions all use the same
- value (xCall, which is equal to 246) for the csCode parameter to the
- XPP parameter block. The xCall routine uses the value of the
- xppSubCode parameter to distinguish between the functions, as
- follows:
-
- Function xppSubCode Value
- GetMyZone zipGetMyZone 7
- GetLocalZones zipGetLocalZones 5
- GetZoneList zipGetZoneList 6
- _________________________________________________
-
- FUNCTION GetMyZone (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word routine
- selector; always xCall
- Æ 28 xppSubCode word routine selector;
- zipGetMyZone
- Æ 30 xppTimeOut byte retry interval in
- seconds
- Æ 31 xppRetry byte retry count
- Æ 34 zipBuffPtr long pointer to data
- buffer
- Æ 42 zipInfoField 70 bytes for use by ZIP; first
- word set to 0
-
- The GetMyZone function returns only the AppleTalk zone name of the node on which
- your application is running.
-
- The ioResult parameter returns the result of the function. If you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The csCode and xppSubCode parameters are routine selectors and are
- automatically set by the MPW interface to xCall and zipGetMyZone for this
- function. The xppTimeOut field specifies the amount of time, in seconds, that
- the .ATP driver should wait between attempts to obtain the data. A value of 3 or
- 4 for the xppTimeOut field generally gives good results. The xppRetry field
- specifies the number of times the .ATP driver should attempt to obtain the data
- before returning the ReqFailed (request failed) result code. A value of 3 or 4
- for the xppRetry field usually works well.
-
- The zipBuffPtr is a pointer to a 33-byte data buffer that you must allocate. ZIP
- returns the zone name into this buffer as a Pascal string. The zipInfo field is
- a 70-byte data buffer that you must allocate for use by ZIP. You must set the
- first word of this buffer to 0 before you call the GetMyZone function.
-
- Result codes
- noErr 0 No error
- noBridgeErr –93 No router is available
- reqFailed –1096 Request to contact router failed;
- retry count exceeded
- tooManyReqs –1097 Too many concurrent requests
- noDataArea –1104 Too many outstanding ATP calls
-
- FUNCTION GetLocalZones (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word routine selector; always
- xCall
- Æ 28 xppSubCode word routine selector;
- zipGetLocalZones
- Æ 30 xppTimeOut byte retry interval in seconds
- Æ 31 xppRetry byte retry count
- Æ 34 zipBuffPtr long pointer to data buffer
- ¨ 38 zipNumZones word number of names returned
- ¨ 40 zipLastFlag byte nonzero if no more names
- Æ 42 zipInfoField 70 bytes for use by ZIP; first word set
- to 0
-
- The GetLocalZones function returns a list of all the zone names on the local
- network; that is, the network that includes the node on which your application
- is running.
-
- The ioResult parameter returns the result of the function. If you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The csCode and xppSubCode parameters are routine selectors and are
- automatically set by the MPW interface to xCall and zipGetLocalZones for this
- function. The xppTimeOut field specifies the amount of time, in seconds, that
- the .ATP driver should wait between attempts to obtain the data. A value of 3 or
- 4 for the xppTimeOut field generally gives good results. The xppRetry field
- specifies the number of times the .ATP driver should attempt to obtain the data
- before returning the ReqFailed (request failed) result code. A value of 3 or 4
- for the xppRetry field usually works well.
-
- The zipBuffPtr field is a pointer to a 578-byte data buffer that you must
- allocate. ZIP returns the zone names into this buffer as a packed array of
- packed Pascal strings. The zipNumZones parameter returns the number of zone
- names that ZIP placed in the data buffer.
-
- The .XPP driver sets the zipLastFlag field to 1 if there are no more zone names
- for your network. If the zipLastFlag field is still 0 when the GetLocalZones
- function has completed execution, you must empty the data buffer pointed to by
- the zipBuffPtr parameter and immediately call the GetLocalZones function again
- without changing the value in the zipInfoField parameter. The zipInfoField
- parameter is a 70-byte data buffer that you must allocate for use by ZIP. You
- must set the first word of this buffer to 0 before you call the GetLocalZones
- function the first time, and you must not change the contents of this field
- thereafter.
-
- Result codes
- noErr 0 No error
- noBridgeErr –93 No router is available
- reqFailed –1096 Request to contact router failed;
- retry count exceeded
- tooManyReqs –1097 Too many concurrent requests
- noDataArea –1104 Too many outstanding ATP calls
-
- FUNCTION GetZoneList (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word routine
- selector; always xCall
- Æ 28 xppSubCode word routine selector;
- zipGetZoneList
- Æ 30 xppTimeOut byte retry interval in
- seconds
- Æ 31 xppRetry byte retry count
- Æ 34 zipBuffPtr long pointer to data
- buffer
- ¨ 38 zipNumZones word number of names returned
- ¨ 40 zipLastFlag byte nonzero if no
- more names
- Æ 42 zipInfoField 70 bytes for use by ZIP;
- first word set to 0
-
- The GetZoneList function returns a complete list of all the zone names on the
- internet. To obtain a list of only the zone names on the local network, use the
- GetLocalZones function instead.
-
- The ioResult parameter returns the result of the function. If you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The csCode and xppSubCode parameters are routine selectors and are
- automatically set by the MPW interface to xCall and zipGetZoneList for this
- function. The xppTimeOut field specifies the amount of time, in seconds, that
- the .ATP driver should wait between attempts to obtain the data. A value of 3 or
- 4 for the xppTimeOut field generally gives good results. The xppRetry field
- specifies the number of times the .ATP driver should attempt to obtain the data
- before returning the ReqFailed (request failed) result code. A value of 3 or 4
- for the xppRetry field usually works well.
-
- The zipBuffPtr field is a pointer to a 578-byte data buffer that you must
- allocate. ZIP returns the zone names into this buffer as Pascal strings. The
- zipNumZones parameter returns the number of zone names that ZIP placed in the
- data buffer.
-
- The .XPP driver sets the zipLastFlag field to 1 if there are no more zone names
- for the internet. If the zipLastFlag field is still 0 when the GetZoneList
- function has completed execution, you must empty the data buffer pointed to by
- the zipBuffPtr parameter and immediately call the GetZoneList function again
- without changing the value in the zipInfoField parameter. The zipInfoField
- parameter is a 70-byte data buffer that you must allocate for use by ZIP. You
- must set the first word of this buffer to 0 before you call the GetZoneList
- function the first time, and not change the contents of this field thereafter.
-
- If you use the GetZoneList function on an nonextended network, it returns the
- reqFailed result code.
-
- Result codes
- noErr 0 No error
- noBridgeErr –93 No router is available
- reqFailed –1096 Request to contact router failed;
- retry count exceeded
- tooManyReqs –1097 Too many concurrent requests
- noDataArea –1104 Too many outstanding ATP calls
- _______________________________________________________________________________
-
- æKY Appletalk…Data…Stream…Protocol…(adsp)…Volume…VI
- æC »Appletalk Data Stream Protocol (adsp) Volume VI AppleTalk Manager
- _______________________________________________________________________________
-
- One of the significant new features of AppleTalk included as part of system
- software version 7.0 is the AppleTalk Data Stream Protocol (ADSP), which
- provides a full-duplex data stream connection between two nodes in an AppleTalk
- internet. Like the AppleTalk Session Protocol, Printer Access Protocol, and
- AppleTalk Transaction Protocol, ADSP uses the Datagram Delivery Protocol to send
- its data over the internet. Therefore, even though ADSP appears to its clients
- to handle data as a stream of bytes, the data is actually transmitted and
- received by DDP in packets. ADSP takes advantage of this fact by including
- control and status information in the DDP packet header. You can use the .DSP
- driver routines described in “.DSP Driver Routines,” later in this chapter, to
- control an ADSP connection. The .DSP driver takes care of implementation of ADSP
- for you.
-
- Every ADSP connection is between two sockets in an AppleTalk internet. Each
- socket can maintain concurrent ADSP connections with several other sockets, but
- there can be only one ADSP connection between any two sockets at one time. When
- a pair of sockets establishes an ADSP connection, each socket client initializes
- and maintains a certain amount of control and state information that it uses for
- synchronizing communication with the other socket client and for error checking.
-
-
- The combination of a socket and the ADSP information maintained by the socket
- client is referred to as a connection end. When two connection ends establish
- communication, the connection is considered an open connection. When both
- connection ends terminate the link and dispose of the connection information
- each maintains, the connection is considered a closed connection. If one
- connection end is established but the other connection end is unreachable or has
- disposed of its connection information, the connection is considered a half-open
- connection. No communication can occur over a half-open or closed connection. To
- prevent a half-open connection from tying up resources, ADSP automatically
- closes any half-open connection that cannot reestablish communications within 2
- minutes.
-
- _______________________________________________________________________________
-
- æKY Using…ADSP
- æC »Using ADSP AppleTalk Manager
- _______________________________________________________________________________
-
- You can use ADSP to implement a data stream connection between any two sockets
- on an internet. (Note that although there can be only one ADSP connection
- between any two sockets, a single socket can maintain connections with several
- other sockets.) This section describes how to open, maintain, and close a
- connection between two sockets on an internet. It also describes how to
- establish and use a connection listener; that is, a connection end that waits
- passively to receive a connection request and then passes the connection request
- on to its client, the connection server. Finally, this section describes how to
- write a routine (referred to as a user routine ) that ADSP calls when your
- connection end receives an unsolicited connection event.
-
- _______________________________________________________________________________
-
- æKY The…ADSP…Connection…Control…Block
- æC »The ADSP Connection Control Block AppleTalk Manager
- _______________________________________________________________________________
-
- When you establish an ADSP connection end, you must allocate a nonrelocatable
- block of memory for, and provide a pointer to, a connection control block (CCB)
- data structure, which is used by ADSP to store state information about the
- connection end. You may read the fields in the CCB to obtain information about
- the connection end, but you are not allowed to write to any of the fields except
- one, the userFlags field. The CCB requires 242 bytes and is defined by the TRCCB
- data type.
-
- TYPE TRCCB =
- PACKED RECORD
- ccbLink: TPCCB; {link to next CCB}
- refNum: Integer; {reference number}
- state: Integer; {state of the connection end}
- userFlags: Byte; {user flags for connection}
- localSocket: Byte; {local socket number}
- remoteAddress: AddrBlock; {remote end internet address}
- attnCode: Integer; {attention code received}
- attnSize: Integer; {size of attention data}
- attnPtr: Ptr; {pointer to attention data}
- reserved: PACKED ARRAY[1..220] OF Byte
- {reserved for use by ADSP}
- END;
-
- The internet address of the remote connection end is defined in the TRCCB record
- by the AddrBlock data type:
-
- TYPE AddrBlock =
- PACKED RECORD
- aNet: Integer; {network number}
- aNode: Byte; {node ID}
- aSocket: Byte {socket number}
- END;
-
- Field descriptions
-
- ccbLink A pointer to the next CCB. This field is for use by ADSP only.
-
- refNum The reference number of the CCB. This number is assigned by ADSP
- when you establish the connection end.
-
- state The state of the connection end, as follows:
-
- State Value Meaning
-
- sListening 1 The socket is a
- connection listening socket;
- that is, a
- socket
- that
- accepts
- ADSP
- requests
- to
- open
-
- and passes
- them on to
- a
- socket
- client.
- This state
- is
- ordinarily
- used
- only by
- connection
- servers.
-
- sPassive 2 The socket client
- is inactive but capable of
- accepting
- an ADSP
- request
- to open a
-
- Unlike a
-
- listening
- socket,
- which
- passes
- the
-
-
- request
- on to a
- routine
- that can
- establish
- the
-
- on any
- socket, a
- socket
- client in
- the
- sPassive
- state can
- accept an
-
- request
- only to
- establish
- itself as
- a
-
- end.
-
- sOpening 3 The socket client
- has sent an
-
- request
- and is
- waiting
- for
-
-
-
- sOpen 4 The connection
- is open.
-
- sClosing 5 The socket client
- has requested that ADSP
- close
- the
-
- and ADSP
- is
- sending
- data or
- waiting
- for
-
- of data
- it has
- sent
- before
- closing
- the
-
-
-
- sClosed 6 Either
- connection end or ADSP has closed
- the
-
-
-
- userFlags Flags that indicate an unsolicited connection event has
- occurred. An
- unsolicited connection event is an event initiated by
- ADSP or the
- remote connection end that is not in response to any
- .DSP routine
- that you executed. .i.AppleTalk Data Stream
- Protocol:user flags 32-
-
- Each time an unsolicited connection event occurs,
- ADSP sets a flag
- in the userFlags field of the CCB and calls the
- routine you specified
- in the userRoutine parameter to the dspInit routine
- (if any). The
- user routine must read the userFlags field and then
- clear the flag to
- 0. ADSP cannot notify your routine of future events
- unless you clear
- the flag after each event.
-
- ADSP recognizes four types of unsolicited connection
- events, one
- corresponding to each of the flags in this field.
- The events and flags
- are defined as follows, where bit 7 is the most
- significant bit:
-
- Event Flag bit Meaning
-
- eClosed 7 ADSP has
- been informed by the remote
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- eTearDown 6 ADSP has
- determined that the remote
-
-
- is
-
-
-
- so
-
-
-
-
-
-
- eAttention 5 ADSP has
- received an attention
-
-
-
-
-
-
-
-
-
- eFwdReset 4 ADSP has
- received a forward reset
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- in
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- none 3–0 Reserved.
-
- localSocket The socket number through which DDP transmits and receives
- the ADSP packets.
-
- remoteAddress The internet address of the socket used by the remote connection
- end.
-
- attnCode The attention code received by ADSP when the remote
- connection end sends an attention message.
-
- attnSize The size of the attention message received by ADSP when
- the
- remote connection end sends an attention
- message.
-
- attnPtr A pointer to a buffer containing the attention
- message received
- by ADSP from the remote connection end.
-
- reserved A data buffer reserved for use by ADSP.
-
- _______________________________________________________________________________
-
- æKY The….DSP…Parameter…Block
- æC »The .DSP Parameter Block AppleTalk Manager
- _______________________________________________________________________________
-
- You execute the .DSP routines by calling the Device Manager’s PBControl
- function. Each time you call a .DSP routine, you provide a pointer to a
- parameter block that includes all of the parameters needed by that command.
-
- The .DSP parameter block, defined by the DSPParamBlock data type, is a variant
- parameter block for the PBControl function.
-
- TYPE DSPParamBlock =
- PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: Integer; {queue type}
- ioTrap: Integer; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OsErr; {result code}
- ioNamePtr: StringPtr; {used only for dspOpen}
- ioVRefNum: Integer; {volume reference number}
- ioCRefNum: Integer; {driver reference number}
- csCode: Integer; {primary command code}
- qStatus: LongInt; {reserved for ADSP}
- ccbRefNum: Integer; {CCB reference number}
-
- CASE Integer OF
- dspInit,
- dspCLInit:
- (
- ccbPtr: TPCCB; {pointer to CCB}
- userRoutine: ProcPtr; {pointer to user routine}
- sendQSize: Integer; {size of send queue}
- sendQueue: Ptr; {pointer to send queue}
- recvQSize: Integer; {size of receive queue}
- recvQueue: Ptr; {pointer to receive queue}
- attnPtr: Ptr; {pointer to attention- }
- { message buffer}
- localSocket: Byte; {local socket number}
- filler1: Byte; {filler for proper alignment}
- );
-
- dspOpen,
- dspCLListen,
- dspCLDeny:
- (
- localCID: Integer; {local connection ID}
- remoteCID: Integer; {remote connection ID}
- remoteAddress: AddrBlock; {remote internet address}
- filterAddress: AddrBlock; {address filter}
- sendSeq: LongInt; {send sequence number}
- sendWindow: Integer; {size of remote buffer}
- recvSeq: LongInt; {receive sequence number}
- attnSendSeq: LongInt; {attention send seq number}
- attnRecvSeq: LongInt; {attention receive seq num}
- ocMode: Byte; {connection opening mode}
- ocInterval: Byte; {interval bet open requests}
- ocMaximum: Byte; {retries of open conn req}
- filler2: Byte; {filler for proper alignment}
- );
-
- dspClose,
- dspRemove:
- (
- abort: Byte; {abort send requests}
- filler3: Byte; {filler for proper alignment}
- );
-
- dspStatus:
- (
- statusCCB: TPCCB; {pointer to CCB}
- sendQPending: Integer; {bytes waiting in send queue}
- sendQFree: Integer; {available send-queue buffer}
- recvQPending: Integer; {bytes in receive queue}
- recvQFree: Integer; {avail receive-queue buffer}
- )
-
- dspRead,
- dspWrite:
- (
- reqCount: Integer; {requested number of bytes}
- actCount: Integer; {actual number of bytes}
- dataPtr: Ptr; {pointer to data buffer}
- eom: Byte; {1 if end of message}
- flush: Byte; {1 to send data now}
- )
-
- dspAttention:
- (
- attnCode: Integer; {client attention code}
- attnSize: Integer; {size of attention data}
- attnData Ptr; {pointer to attention data}
- attnInterval: Byte; {reserved}
- filler4: Byte; {filler for proper alignment}
- )
-
- dspOptions:
- (
- sendBlocking: Integer; {send-blocking threshold}
- sendTimer: Byte; {reserved}
- rtmtTimer: Byte; {reserved}
- badSeqMax: Byte; {retransmit advice threshold}
- useCheckSum: Byte; {DDP checksum for packets}
- )
-
- dspNewCID:
- (
- newCID: Integer; {new connection ID}
- )
- END;
-
- The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and ioVRefNum fields are filled
- in by the Device Manager; your application should not have to set or read these
- fields. The ioResult field returns the result of the function. If you call the
- routine asynchronously, the Device Manager sets this field to 1 as soon as you
- call the routine and it changes the field to the actual result code when the
- routine completes execution. The ioCompletion field is a pointer to a completion
- routine that you can provide; the Device Manager calls your completion routine
- when it completes execution of the PBControl function. If you are not providing
- a completion routine, specify NIL for this field.
-
- The ioCRefNum field is returned by the OpenDriver function. You must specify
- this number every time you call the .DSP driver.
-
- The csCode field specifies the command to be executed. You must fill in this
- field before calling the PBControl function. You can use the following constants
- as values for the csCode field:
-
- CONST {ADSP routine selectors}
- dspInit = 255; {create a new connection end}
- dspRemove = 254; {remove a connection end}
- dspOpen = 253; {open a connection}
- dspClose = 252; {close a connection}
- dspCLInit = 251; {create a connection listener}
- dspCLRemove = 250; {remove a connection listener}
- dspCLListen = 249; {post a listener request}
- dspCLDeny = 248; {deny an open-connection request}
- dspStatus = 247; {get status of connection end}
- dspRead = 246; {read data from the connection}
- dspWrite = 245; {write data on the connection}
- dspAttention = 244; {send an attention message}
- dspOptions = 243; {set connection end options}
- dspReset = 242; {forward reset the connection}
- dspNewCID = 241; {generate a cid for a connection end}
-
- The qStatus field is reserved for use by ADSP. The ccbRefNum field is the
- reference number of the CCB. The CCB reference number is returned by ADSP in
- response to the dspInit routine. You must specify this number as a parameter to
- every .DSP driver routine you call subsequently.
-
- The remaining fields are used only for specific routines; each of these fields
- is described in “.DSP Driver Routines” later in this chapter.
-
- _______________________________________________________________________________
-
- æKY Opening…and…Maintaining…an…ADSP…Connection
- æC »Opening and Maintaining an ADSP Connection AppleTalk Manager
- _______________________________________________________________________________
-
- To use the AppleTalk Data Stream Protocol (ADSP) to establish and maintain a
- connection between a socket on your local node and a remote socket, use the
- following procedure:
-
- 1. Use the MPPOpen function to open the .MPP driver, and then use the
- OpenDriver function to open the .DSP driver. The OpenDriver function
- returns the reference number for the .DSP driver. You must supply this
- reference number each time you call the .DSP driver.
-
- 2. Allocate nonrelocatable memory for a connection control block (CCB), send
- and receive queues, and an attention message buffer. If you need to
- allocate the
- memory dynamically while the program is running, use the NewPtr routine.
- Otherwise, the way in which you allocate the memory depends on the
- compiler you are using. (Listing 32-4 at the end of this section shows
- how it’s
- done in Pascal). The memory that you allocate becomes the property of
- ADSP
- when you call the dspInit routine to establish a connection end. You
- cannot
- write any data to this memory except by calling ADSP, and you must
- ensure
- that the memory remains locked until you call the dspRemove routine to
- eliminate the connection end.
-
- The CCB is 242 bytes. The attention-message buffer must be 570 bytes.
- When
- you send bytes to a remote connection end, ADSP stores the bytes in a
- buffer
- called the send queue . Until the remote connection end acknowledges
- their
- receipt, ADSP keeps the bytes you sent in the send queue so that they
- are
- available to be retransmitted if necessary. When the local connection
- end
- receives bytes, it stores them in a buffer, called the receive queue,
- until you
- read them. The sizes you need for the send and receive queues depend on
- the
- lengths of the messages being sent.
-
- ADSP does not transmit data from the remote connection end until there
- is
- room for it in your receive queue. If your send or receive queues are
- too small,
- they limit the speed with which you can transmit and receive data. A
- queue
- size of 600 bytes should work well for most applications. If you are
- using ADSP
- to send a continuous flow of data, a larger data buffer improves
- performance.
- If your application is sending or receiving the user’s keystrokes, a
- smaller
- buffer should be adequate. The constant minDSPQueueSize indicates the
- minimum queue size that you can use.
-
- If you are using a version of the .DSP driver prior to version 1.5, you
- must
- allocate send and receive queues that are 12% larger than the actual
- buffer
- sizes you need. You must do this in order to provide some extra space
- for use
- by the .DSP driver. Version 1.5 and later versions of the .DSP driver
- use a
- much smaller, and variable, portion of buffer space for overhead. The
- .DSP
- driver version number is stored in the low byte of the qFlags field,
- which is
- the first field in the dCtlQHdr field in the driver’s device control
- entry (DCE)
- data structure. Version 1.5 of the .DSP driver has a version number of
- 4 in the
- DCE. The DCE is described in the Device Manager chapters of Volumes II
- and
- V.
-
- 3. Use the dspInit routine to establish a connection end. You must provide
- pointers to the CCB, send queue, receive queue, and attention-message
- buffer.
- You may also provide a pointer to the user routine that ADSP calls when
- your
- connection end receives an unsolicited connection event. User routines
- are
- discussed in “Writing a User Routine for Connection Events” later in
- this
- chapter.
-
- If there is a specific socket that you want to use for the connection
- end, you can
- specify the socket number in the localSocket parameter. If you want
- ADSP to
- assign the socket for you, specify 0 for the localSocket parameter.
- ADSP returns
- the socket number when the dspInit routine completes execution.
-
- 4. If you wish, you can use the NBPRegister function to add the name and
- address of your connection end to the node’s names table. The
- NBPRegister
- function is described in the AppleTalk Manager chapter of Volume II.
-
- 5. You can use the dspOptions routine to set several parameters that control
- the
- behavior of the connection end. Because every parameter has a default
- value,
- the use of the dspOptions routine is optional. You can specify values
- for the
- following parameters:
-
- • The sendBlocking parameter, which sets the maximum number of bytes
- that may accumulate in the send queue before ADSP sends a packet
- to the
- remote connection end. You can experiment with different values
- of the
- sendBlocking parameter to determine which provides the best
- performance. Under most circumstances, the default value of
- 16 bytes gives
- good performance.
-
- • The badSeqMax parameter, which sets the maximum number of
- out-of-sequence data packets that the local connection end can
- receive
- before requesting the remote connection end to retransmit the
- missing
- data. Under most circumstances, the default value of 3 provides
- good
- performance.
-
- • The useCheckSum parameter, which determines whether the Datagram
- Delivery Protocol (DDP) should compute a checksum and include it in
- each
- packet that it sends to the remote connection end. Using checksums
- slows
- communications slightly. Normally ADSP and DDP perform enough error
- checking to ensure safe delivery of all data. Set the useCheckSum
- parameter
- to 1 only if you feel that the network is highly unreliable.
-
- 6. Call the dspOpen routine to open the connection. The dspOpen routine has
- four possible modes of operation: ocAccept, ocEstablish, ocRequest, and
- ocPassive. Normally you use either the ocRequest or ocPassive mode. You
- must specify one of these four modes for the ocMode parameter when you
- call
- the dspOpen routine.
-
- The ocAccept mode is used only by connection servers. The ocEstablish
- mode is
- used by routines that determine their connection-opening parameters and
- establish a connection independently of ADSP, but use ADSP to transmit
- and
- receive data.
-
- Use the ocRequest mode when you want to establish communications with a
- specific socket on the internet. When you execute the dspOpen routine in
- the
- ocRequest mode, ADSP sends an open-connection request to the address you
- specify.
-
- If the socket to which you send the open-connection request is a
- connection
- listener, the connection server that operates that connection listener
- can
- choose any socket on the internet to be the connection end that responds
- to the
- open-connection request. To restrict the socket from which you will
- accept a
- response to your open-connection request, specify a value for the
- filterAddress
- parameter to the dspOpen routine. When your connection end receives a
- response from a socket that meets the restrictions of the filterAddress
- parameter, it acknowledges the response and ADSP completes the
- connection.
-
- To use the ocRequest mode, you must know the complete internet address
- of
- the remote socket, and the ADSP client at that address must either be a
- connection listener or have executed the dspOpen routine in the
- ocPassive
- mode. You can use the PLookupName function to obtain a list of names of
- objects on the internet and to determine the internet address of a
- socket when
- you know its name. The PLookupName function is the preferred interface
- version of the NBPLookup function. The NBPLookup function is described
- in
- the AppleTalk Manager chapter of Volume II. The preferred interface is
- described in the AppleTalk Manager chapter of Volume V. Enhancements to
- the wildcard-lookup feature of the Name-Binding Protocol (NBP) are
- discussed
- in “A New NBP Wildcard Character” earlier in this chapter.
-
- Use the ocPassive mode when you expect to receive an open-connection
- request from a remote socket. You can specify a value for the
- filterAddress
- parameter to restrict the network number, node ID, or socket number from
- which you will accept an open-connection request. When your connection
- end
- receives an open-connection request that meets the restrictions of the
- filterAddress parameter, it acknowledges the request and ADSP completes
- the
- connection.
-
- You can poll the state field in the CCB to determine when the connection
- end
- is waiting to receive an open-connection request, when the connection
- end is
- waiting to receive an acknowledgment of an open-connection request, and
- when the connection is open. (The CCB is described in “The ADSP
- Connection
- Control Block” earlier in this chapter.) Alternatively, you can check
- the result
- code for the dspOpen routine when the routine completes execution. If
- the
- routine returns the noErr result code, then the connection is open.
-
- 7. Use the dspRead routine to read data that your connection end has
- received
- from the remote connection end. Use the dspWrite routine to send data
- to the
- remote connection end. Use the dspAttention routine to send attention
- messages to the remote connection end.
-
- The dspWrite routine places data in the send queue. ADSP is a
- full-duplex,
- symmetric communications protocol. You can send data at any time, and
- your
- connection end can receive data at any time, even at the same time as
- you are
- sending data. ADSP transmits the data in the send queue when one of the
- following conditions occurs:
-
- • You call the dspWrite routine with the flush parameter set to a
- nonzero
- number.
-
- • The number of bytes in the send queue equals or exceeds the
- blocking
- factor that you set with the dspOptions routine.
-
- • The send timer expires. The send timer sets the maximum amount of
- time that can pass before ADSP sends all unsent data in the
- send queue to
- the remote connection end. ADSP calculates the best value to
- use for this
- timer and sets it automatically.
-
- • A connection event requires that the local connection end send an
- acknowledgment packet to the remote connection end.
-
- If you send more data to the send queue than it can hold, the dspWrite
-
- routine does not complete execution until it has written all the data
- to the
- send queue. If you execute the dspWrite routine asynchronously, ADSP
- returns control to your program and writes the data to the send queue
- as
- quickly as it can. This technique provides the most efficient use of
- the send
- queue by your program and by ADSP. Because ADSP does not remove data
- from the send queue until that data has not only been sent but also
- acknowledged by the remote connection end, using the flush parameter
- to the
- dspWrite routine does not guarantee that the send queue is empty. You
- can
- use the dspStatus routine to determine how much free buffer space is
- available in the send queue.
-
- The dspRead routine reads data from the receive queue into your
- application’s
- private data buffer. ADSP does not transmit data until there is space
- available
- in the other end’s receive queue to accept it. Because a full receive
- queue
- slows the communications rate, you should read data from the receive
- queue
- as often as necessary to keep sufficient buffer space available for
- new data. You
- can use either of two techniques to do this:
-
- • Allocate a small receive queue (about 600 bytes) and call the
- dspRead
- routine asynchronously. Your completion routine for the dspRead
- routine
- should then call the dspRead routine again.
-
- • Allocate a large receive queue and call the dspRead routine less
- frequently.
-
- If there is less data in the receive queue than the amount you
- specify with the
- reqCount parameter to the dspRead command, the command does not
- complete execution until there is enough data available to satisfy
- the request.
- There are three exceptions to this rule:
-
- • If the end-of-message bit in the ADSP packet header is set, the
- dspRead
- command reads the data in the receive queue, returns the actual
- amount
- of data read in the actCount parameter, and returns the eom
- parameter set
- to 1.
-
- • If you have closed the connection end before calling the dspRead
- routine
- (that is, the connection is half open), the command reads
- whatever data
- is available and returns the actual amount of data read in the
- actCount
- parameter.
-
- • If ADSP has closed the connection before you call the dspRead
- routine
- and there is no data in the receive queue, the routine returns
- the noErr
- result code with the actCount parameter set to 0 and the eom
- parameter
- set to 0.
-
- In addition to the byte-stream data format implemented by the dspRead
- and
- dspWrite routines, ADSP provides a mechanism for sending and
- receiving
- control signals or information separate from the byte stream. You use
- the
- dspAttention routine to send an attention code and an attention
- message to
- the remote connection end. When your connection end receives an
- attention
- message, ADSP’s interrupt handler sets the eAttention flag in the
- userFlags
- field of the CCB and calls your user routine. Your user routine must
- first
- clear the userFlags field. Then your routine can read the attention
- code and
- attention message and take whatever action you deem appropriate.
-
- Because ADSP is often used by terminal emulation programs and other
- applications that pass the data they receive on to the user without
- processing
- it, attention messages provide a mechanism for the applications that
- are
- clients of the connection ends to communicate with each other. For
- example,
- you could use attention messages to implement a handshaking and
- data-checking protocol for a program that transfers disk files between
- two
- applications, neither one of which is a file server. Or a database
- server on a
- mainframe computer that uses ADSP to communicate with Macintosh
- computer workstations could use the attention mechanism to inform the
- workstations when the database is about to be closed down for
- maintenance.
-
- 8. When you are ready to close the ADSP connection, you can use the dspClose
- or
- dspRemove routines to close the connection end. Use the dspClose routine
- if
- you intend to use that connection end to open another connection and do
- not
- want to release the memory you allocated for the connection end. Use the
- dspRemove routine if you are completely finished with the connection end
- and want to release the memory.
-
- You can continue to read data from the receive queue after you have
- called the
- dspClose routine, but not after you have called the dspRemove routine.
- You
- can use the dspStatus routine to determine whether any data is remaining
- in
- the receive queue, or you can read data from the receive queue until
- both the
- actCount and eom fields of the dspRead parameter block return 0.
-
- If you set the abort parameter for the dspClose or dspRemove routines to
- 0,
- then ADSP does not close the connection or the connection end until it
- has
- sent—and received acknowledgment for—all data in the send queue and any
- pending attention messages. If you set the abort parameter to 1, then
- ADSP
- discards any data in the send queue and any attention messages that have
- not
- already been sent.
-
- After you have executed the dspRemove routine, you can release the
- memory
- you allocated for the CCB and data buffers.
-
- Listing 32-4 illustrates the use of ADSP. This routine opens the .MPP and .DSP
- drivers and allocates memory for its internal data buffers, for the CCB, and for
- the send, receive, and attention-message buffers. Then the routine uses the
- dspInit routine to establish a connection end and uses NBP to register the name
- of the connection end on the internet. (The user routine specified by the
- userRoutine parameter to the dspInit function is shown in Listing 326.) Next,
- Listing 32-4 uses the dspOptions routine to set the blocking factor to 24 bytes.
- The routine uses NBP to determine the address of a socket whose name was chosen
- by the user and sends an open-connection request (dspOpen) to that socket. When
- the dspOpen routine completes execution, the routine sends data and an attention
- message to the remote connection end and reads data from its receive queue.
- Finally, the routine closes the connection end with the dspRemove routine and
- releases the memory it allocated.
-
- ¿ Listing 32-4 Using ADSP to establish and use a connection
-
- PROCEDURE MyADSP;
-
- CONST
- qSize= 600; {queue space}
- myDataSize= 128; {size of internal read/write buffers}
- blockFact= 24; {blocking factor}
- TYPE
- {modify the connection control block to add storage for A5}
- myTRCCB = RECORD
- myA5: longint;
- u: TRCCB;
- END;
- VAR
- dspSendQPtr: Ptr;
- dspRecvQPtr: Ptr;
- dspAttnBufPtr: Ptr;
- myData2ReadPtr: Ptr;
- myData2WritePtr: Ptr;
- myAttnMsgPtr: Ptr;
- dspCCB: myTRCCB;
- myDSPPBPtr: DSPPBPtr;
- myMPPPBPtr: MPPPBPtr;
- myNTEName: NamesTableEntry;
- myAddrBlk: AddrBlock;
- drvrRefNum: Integer;
- mppRefNum: Integer;
- connRefNum: Integer;
- gReceivedAnEvent: Boolean;
- myAttnCode: Integer;
- tempFlag: Byte;
- tempCFlag: Integer;
- myErr: OSErr;
-
- BEGIN
- myErr := OpenDriver('.MPP', mppRefNum); {open .MPP driver}
- IF myErr <> noErr THEN DoErr(myErr); {check and handle error}
- myErr := OpenDriver('.DSP', drvrRefNum); {open .DSP driver}
- IF myErr <> noErr THEN DoErr(myErr); {check and handle error}
-
- {allocate memory for data buffers}
- dspSendQPtr := NewPtr(qSize); {ADSP use only}
- dspRecvQPtr := NewPtr(qSize); {ADSP use only}
- dspAttnBufPtr := NewPtr(attnBufSize); {ADSP use only}
- myData2ReadPtr := NewPtr(myDataSize);
- myData2WritePtr := NewPtr(myDataSize);
- myAttnMsgPtr := NewPtr(myDataSize);
- myDSPPBPtr := DSPPBPtr(NewPtr(SizeOf(DSPParamBlock)));
- myMPPPBPtr := MPPPBPtr(NewPtr(SizeOf(MPPParamBlock)));
-
- WITH myDSPPBPtr^ DO {set up dspInit parameters}
- BEGIN
- ioCRefNum := drvrRefNum; {ADSP driver ref num}
- csCode := dspInit;
- ccbPtr := @dspCCB; {pointer to CCB}
- userRoutine := @myConnectionEvtUserRoutine;
- {see Listing 32-6}
- sendQSize := qSize; {size of send queue}
- sendQueue := dspSendQPtr; {send-queue buffer}
- recvQSize := qSize; {size of receive queue}
- recvQueue := dspRecvQPtr; {receive-queue buffer}
- attnPtr := dspAttnBufPtr; {receive-attention buffer}
- localSocket := 0; {let ADSP assign socket}
- END;
-
- gReceivedAnEvent := FALSE;
- dspCCB.myA5 := SetCurrentA5; {save A5 for the user routine}
- {establish a connection end}
- myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
- IF myErr <> noErr THEN DoErr(myErr); {check and handle error}
- connRefNum := myDSPPBPtr^.ccbRefNum; {save CCB ref num for later}
-
- NBPSetNTE(@myNTEName, 'The Object', 'The Type',
- '*', myDSPPBPtr^.localSocket);
- {set up NBP names table entry}
- WITH myMPPPBPtr^ DO {set up PRegisterName }
- { parameters}
- BEGIN
- interval := 7; {retransmit every 7*8=56 ticks}
- count := 3; {and retry 3 times}
- entityPtr := @myNTEName; {name to register}
- verifyFlag := 0; {don't verify this name}
- END;
- {register this socket}
- myErr := PRegisterName(myMPPPBPtr, FALSE);
- {register this socket}
- IF myErr <> noErr THEN DoErr(myErr); {check and handle error}
-
- WITH myDSPPBPtr^ DO {set up dspOptions parameters}
- BEGIN
- ioCRefNum := drvrRefNum; {ADSP driver ref num}
- csCode := dspOptions;
- ccbRefNum := connRefNum; {connection ref num}
- sendBlocking := blockFact; {quantum for data packet}
- badSeqMax := 0: {use default}
- useCheckSum := 0; {don't calculate checksum}
- END;
- myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
- {set options}
- IF myErr <> noErr THEN DoErr(myErr); {check and handle error}
-
- PickASocket(myAddrBlk);
- {routine using the PLookupName function to pick a socket }
- { that will be used to establish an open connection}
-
- {open a connection with the chosen socket}
- WITH myDSPPBPtr^ DO {set up dspOpen parameters}
- BEGIN
- ioCRefNum := drvrRefNum; {ADSP driver ref num}
- csCode := dspOpen;
- ccbRefNum := connRefNum; {connection ref num}
- remoteAddress := myAddrBlk; {address of remote socket }
- { from PLookupName function}
- filterAddress := myAddrBlk; {address filter, specified }
- { socket address only}
- ocMode := ocRequest; {open connection mode}
- ocInterval := 0; {use default retry interval}
- ocMaximum := 0; {use default retry maximum}
- END;
- myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
- {open a connection}
- IF myErr <> noErr THEN DoErr(myErr); {check and handle error}
-
- {the connection with the chosen socket is open, so now send to }
- { the send queue exactly myDataSize number of bytes}
- WITH myDSPPBPtr^ DO {set up dspWrite parameters}
- BEGIN
- ioCRefNum := drvrRefNum; {ADSP driver ref num}
- csCode := dspWrite;
- ccbRefNum := connRefNum; {connection ref num}
- reqCount := myDataSize; {write this number of bytes}
- dataPtr := myData2WritePtr; {pointer to send queue}
- eom := 1; {1 means last byte is logical }
- { end-of-message}
- flush := 1; {1 means send data now}
- END;
- myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
- {send data to the remote }
- { connection}
- IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
-
- {now send an attention message to the remote connection end}
- WITH myDSPPBPtr^ DO {set up dspAttention parameters}
- BEGIN
- ioCRefNum := drvrRefNum; {ADSP driver ref num}
- csCode := dspAttention;
- ccbRefNum := connRefNum; {connection ref num}
- attnCode := 0; {user-defined attention code}
- attnSize := myDataSize; {length of attention message}
- attnData := myAttnMsgPtr; {attention message}
- END;
- myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
- IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
-
- {Now read from the receive queue exactly myDataSize number }
- { of bytes.}
- WITH myDSPPBPtr^ DO {set up dspRead parameters}
- BEGIN
- ioCRefNum := drvrRefNum; {ADSP driver ref num}
- csCode := dspRead;
- ccbRefNum := connRefNum; {connection ref num}
- reqCount := myDataSize; {read this number of bytes}
- dataPtr := myData2ReadPtr; {pointer to read buffer}
- END;
- myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
- {read data from the remote }
- { connection}
- IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
-
- {we're done with the connection, so remove it}
- WITH myDSPPBPtr^ DO {set up dspRemove parameters}
- BEGIN
- ioCRefNum := drvrRefNum; {ADSP driver ref num}
- csCode := dspRemove;
- ccbRefNum := connRefNum; {connection ref num}
- abort := 0; {don't close until everything }
- { is sent and received}
- END;
- myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
- {close and remove the connection}
- IF myErr <> noErr THEN DOErr(myErr);{check and handle error}
-
- {we're done with this connection, so give back the memory}
- DisposPtr(dspSendQPtr);
- DisposPtr(dspRecvQPtr);
- DisposPtr(dspAttnBufPtr);
- DisposPtr(myData2ReadPtr);
- DisposPtr(myData2WritePtr);
- DisposPtr(myAttnMsgPtr);
- DisposPtr(Ptr(myDSPPBPtr));
- DisposPtr(Ptr(myMPPPBPtr));
-
- END; {MyADSP}
- _______________________________________________________________________________
-
- æKY Creating…and…Using…a…Connection…Listener
- æC »Creating and Using a Connection Listener AppleTalk Manager
- _______________________________________________________________________________
-
- A connection listener is a special sort of AppleTalk Data Stream Protocol (ADSP)
- connection end that cannot receive or transmit data streams or attention
- messages. The sole function of a connection listener is to wait passively to
- receive an open-connection request and to inform its client, the connection
- server, when it receives one. The connection server can then accept or deny the
- open-connection request. If it accepts the request, the connection server
- selects a socket to use as a connection end, establishes a connection end on
- that socket, and sends an acknowledgment and connection request back to the
- requesting connection end. The connection server can use the same socket as it
- used for the connection listener or can select a different socket as the
- connection end.
-
- Use the following procedure to establish a connection listener and to use that
- connection listener to open a connection with a remote connection end:
-
- 1. Use the MPPOpen function to open the .MPP driver and then use the
- OpenDriver function to open the .DSP driver. The OpenDriver function
- returns the reference number for the .DSP driver. You must supply this
- reference number each time you call the .DSP driver.
-
- 2. Allocate nonrelocatable memory for a connection control block (CCB). (The
- CCB is described in “The ADSP Connection Control Block” earlier in this
- chapter.) A connection listener does not need send and receive queues or
- an
- attention-message buffer. The memory that you allocate becomes the
- property
- of ADSP when you call the dspCLInit routine to establish a connection
- listener.
- You cannot write any data to this memory except by calling ADSP, and you
- must ensure that the memory remains locked until you call the dspRemove
- routine to eliminate the connection end. The CCB is 242 bytes.
-
- 3. Call the dspCLInit routine to establish a connection listener. You must
- provide
- a pointer to the CCB.
-
- If there is a specific socket that you want to use for the connection
- listener, you
- can specify the socket number in the localSocket parameter. If you want
- ADSP
- to assign the socket for you, specify 0 for the localSocket parameter.
- ADSP
- returns the socket number when the dspCLInit routine completes execution.
-
- 4. If you wish, you can use the NBPRegister function to add the name and
- address of your connection listener to the node’s names table. The
- NBPRegister function is described in the AppleTalk Manager chapter of
- Volume II.
-
- 5. Use the dspCLListen routine to cause the connection listener to wait for
- an
- open-connection request. Because the dspCLListen routine does not
- complete
- execution until it receives a connection request, you should call this
- routine
- asynchronously. You can specify a value for the filterAddress parameter
- to
- restrict the network number, node ID, or socket number from which you
- will
- accept an open-connection request.
-
- When the dspCLListen routine receives an open-connection request that
- meets the restrictions of the filterAddress parameter, it returns a
- noErr result
- code (if you executed the routine asynchronously, it places a noErr
- result code
- in the ioResult parameter) and places values in the parameter block for
- the
- remoteCID, remoteAddress, sendSeq, sendWindow, and attnSendSeq
- parameters.
-
- 6. If you want to open the connection, call the dspInit routine to establish
- a
- connection end. You can use any available socket on the node for the
- connection end, including the socket that you used for the connection
- listener.
- Because a single socket can have more than one CCB connected with it,
- the
- socket can function simultaneously as a connection end and a connection
- listener.
-
- You can check the address of the remote socket to determine if it meets
- your
- criteria for a connection end. Although the filterAddress parameter to
- the
- dspCLListen routine provides some screening of socket addresses, it
- cannot
- check for network number ranges, for example, or for a specific set of
- socket
- numbers. If for some reason you want to deny the connection request,
- call the
- dspDeny routine, specifying the CCB of the connection listener in the
- ccbRefNum parameter. Because the dspCLListen routine completes execution
- when it receives an open-connection request, you must return to step 5
- to wait
- for another connection request.
-
- 7. Call the dspOpen routine to open the connection. Specify the value
- ocAccept
- for the ocMode parameter and specify in the ccbRefNum parameter the
- reference number of the CCB for the connection end that you want to use.
- When you call the dspOpen routine, you must provide the values returned
- by
- the dspCLListen routine for the remoteCID, remoteAddress, sendSeq,
- sendWindow, and attnSendSeq parameters.
-
- You can poll the state field in the CCB to determine when the connection
- is
- open. Alternatively, you can check the result code for the dspOpen
- routine
- when the routine completes execution. If the routine returns the noErr
- result
- code, then the connection is open.
-
- 8. You can now send and receive data and attention messages over the
- connection, as described in the preceding section, “Opening and
- Maintaining
- an ADSP Connection.” When you are ready to close the connection, you
- can
- use the dspClose or dspRemove routines, which are also described in the
- preceding section.
-
- 9. When you are finished using the connection listener, you can use the
- dspCLRemove routine to eliminate it. Once you have called the
- dspCLRemove routine, you can release the memory you allocated for the
- connection listener’s CCB.
-
- Listing 32-5 illustrates the use of ADSP to establish and use a connection
- listener. It opens the .MPP and .DSP drivers and allocates memory for the CCB.
- Then it uses the dspCLInit routine to establish a connection listener, uses the
- Name-Binding Protocol (NBP) to register the name of the connection end on the
- internet, and uses the dspCLListen routine to wait for a connection request.
- When the routine receives a connection request, it calls the dspOpen routine to
- complete the connection.
-
- ¿ Listing 32-5 Using ADSP to establish and use a connection listener
-
- VAR
- dspCCBPtr: TPCCB;
- myDSPPBPtr: DSPPBPtr;
- myMPPPBPtr: MPPPBPtr;
- myNTEName: NamesTableEntry;
- drvrRefNum: Integer;
- mppRefNum: Integer;
- connRefNum: Integer;
- myErr: OSErr;
-
- BEGIN
- myErr := OpenDriver('.MPP', mppRefNum); { open .MPP driver }
- IF myErr <> noErr THEN DoErr(myErr); {check and handle error}
- myErr := OpenDriver('.DSP', drvrRefNum); {open .DSP driver}
- IF myErr <> noErr THEN DoErr(myErr); {check and handle error}
-
- {allocate memory for data buffers}
- dspCCBPtr := TPCCB(NewPtr(SizeOf(TRCCB)));
- myDSPPBPtr := DSPPBPtr(NewPtr(SizeOf(DSPParamBlock)));
- myMPPPBPtr := MPPPBPtr(NewPtr(SizeOf(MPPParamBlock)));
-
- WITH myDSPPBPtr^ DO {set up dspCLInit parameters}
- BEGIN
- ioCRefNum := drvrRefNum; {ADSP driver ref num}
- csCode := dspCLInit;
- ccbPtr := dspCCBPtr; {pointer to CCB}
- localSocket := 0; {local socket number}
- END;
- myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
- {establish a connection listener}
-
- IF myErr <> noErr THEN DoErr(myErr); {check and handle error}
- connRefNum := myDSPPBPtr^.ccbRefNum; {save CCB ref num for later}
-
- NBPSetNTE(@myNTEName, 'The Object', 'The Type',
- '*', myDSPPBPtr^.localSocket);
- {set up NBP names table entry}
- WITH myMPPPBPtr^ DO {set up PRegisterName parameters}
- BEGIN
- interval := 7; {retransmit every 7*8=56 ticks}
- count := 3; {and retry 3 times}
- entityPtr := @myNTEname; {name to register}
- verifyFlag := 0; {don't verify this name}
- END;
- myErr := PRegisterName(myMPPPBPtr, FALSE);
- {register this name}
- IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
-
- WITH myDSPPBPtr^ DO {set up dspCLListen parameters}
- BEGIN
- ioCRefNum := drvrRefNum; {ADSP driver ref num}
- csCode := dspCLListen;
- ccbRefNum := connRefNum; {connection ref num}
- filterAddress := AddrBlock(0); {connect with anybody}
- END;
- myErr := PBControl(ParmBlkPtr(myDSPPBPtr), TRUE);
- {listen for connection requests}
- WHILE myDSPPBPtr^.ioResult = 1 DO
- BEGIN
- {return control to user while waiting for }
- { a connection request}
- GoDoSomething;
- END;
- IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
-
- {You received a connection request; now open a connection }
- { The dspCLListen call has returned values into the }
- { remoteCID, remoteAddress, sendSeq, sendWindow, }
- { and attnSendSeq fields of the parameter block.}
-
- WITH myDSPPBPtr^ DO {set up dspOpen parameters}
- BEGIN
- ioCRefNum := drvrRefNum; {ADSP driver ref num}
- csCode := dspOpen;
- ccbRefNum := connRefNum; {connection ref num}
- ocMode := ocAccept; {open connection mode}
- ocInterval := 0; {use default retry interval}
- ocMaximum := 0; {use default retry maximum}
- END;
- myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
- {open a connection}
- IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
-
-
- {Listing 32-4 shows how to use ADSP to maintain a connection.}
-
- END; {MyCLADSP}
-
- _______________________________________________________________________________
-
- æKY Writing…a…User…Routine…for…Connection…Events
- æC »Writing a User Routine for Connection Events AppleTalk Manager
- _______________________________________________________________________________
-
- When you execute the dspInit routine, you can specify a pointer to a routine
- that you provide (referred to as the user routine ). Whenever an unsolicited
- connection event occurs, the AppleTalk Data Stream Protocol (ADSP) sets a flag
- in the connection control block (CCB) and calls the user routine. The user
- routine must clear the flag to acknowledge that it has read the flag field, and
- then can respond to the event in any manner you deem appropriate. The CCB flags
- are described in “The ADSP Connection Control Block” earlier in this chapter.
- The four following types of unsolicited connection events set flags in the CCB:
-
- • ADSP has been informed by the remote connection end that the remote
- connection end is about to close the connection. An appropriate reponse
- might
- be to store a flag indicating that the connection end is about to close.
- When your
- application regains control, it can then display a dialog box informing
- the user
- of this event and asking whether the application should attempt to
- reconnect
- later.
-
- • ADSP has determined that the remote connection end is not responding and so
- has closed the connection. Your user routine can attempt to open a new
- connection immediately. Alternatively, you can store a flag indicating
- that the
- connection has closed, and when your application regains control, it can
- display
- a dialog box asking the user whether to attempt to reconnect.
-
- • ADSP has received an attention message from the remote connection end.
- Depending on what you are using the attention-message mechanism for, you
- might want to read the attention code in the attnCode field of the CCB and
- the
- attention message pointed to by the attnPtr field of the CCB.
-
- • ADSP has received a forward reset command from the remote client end, has
- discarded all ADSP data not yet delivered, including the data in the
- receive
- queue of the local client end, and has resynchronized the connection. Your
- response to this event depends on the purpose for which you are using the
- forward reset mechanism. You might want to resend the last data you have
- sent
- or inform the user of the event.
-
- When ADSP calls your user routine, the CPU is in interrupt-processing mode and
- register A1 contains a pointer to the CCB of the connection end that generated
- the event. You can examine the userFlags field of the CCB to determine what
- event caused the interrupt, and you can examine the state field of the CCB to
- determine the current state of the connection.
-
- Because the CPU is set to interrupt-processing mode, your user routine must
- preserve all registers other than A0, A1, D0, D1, and D2. Your routine must not
- make any direct or indirect calls to the Memory Manager and can’t depend on
- handles to unlocked blocks being valid. If you want to use any of your
- application’s global variables, you must save the contents of the A5 register
- before using the variables, and you must restore the A5 register before your
- routine terminates. Listings 32-4 and 32-6 illustrate the use of the CCB to
- store the pointer to your application’s global variables.
-
- If you want to execute a routine each time an unsolicited connection event
- occurs but the interrupt environment is too restrictive, you can specify a NIL
- pointer to the user routine and periodically poll the userFlags field of the
- CCB.
-
- † Warning: When an unsolicited connection event occurs, you must clear the
- bit in the userFlags field to 0 or the connection will hang. To ensure
- that you
- do not lose any attention messages, you must read any attention messages
- into
- an internal buffer before you clear the bit in the userFlags field. Ê
-
- Listing 32-6 is the user routine called by Listing 32-4. When this routine is
- called, it first checks the CCB to determine the source of the interrupt and
- then clears the bit in the userFlags field of the CCB. If the routine has
- received an attention message, the user routine reads the message into an
- internal buffer before it clears the flag bit. The definitions of procedures
- PushA5, GetMyTRCCBA5, and PopA5 are shown in Listing 32-6 for your convenience.
- In a complete application these procedures would be defined in the calling
- routine (Listing 32-4).
-
- ¿ Listing 32-6 An ADSP user routine
-
- PROCEDURE PushA5; {moves current value of A5 onto stack}
- INLINE $2F0D; {MOVE.L A5,-(SP)}
-
- PROCEDURE GetMyTRCCBA5; {Retrieves A5 from the head of the TRCCB }
- { (pointed to by A1) and sticks it in A5.}
- INLINE $2A69, $FFFC; {MOVE.L -4(A1), A5}
-
- PROCEDURE PopA5; {restores A5 from stack}
- INLINE $2A5F; {MOVE.L (SP)+, A5}
-
- PROCEDURE myConnectionEvtUserRoutine;
-
- BEGIN
- {The connection received an unexpected connection event. Find out }
- { what kind and process accordingly.}
-
- PushA5; {save the current A5}
- GetMyTRCCBA5; {set up A5 to point to your application's }
- { global variables}
-
- WITH dspCCB.u DO
- BEGIN
- IF BAND(userFlags, eClosed) <> 0 THEN TellUserItsClosed;
- IF BAND(userFlags, eTearDown) <> 0 THEN TellUserItsBroken;
- IF BAND(userFlags, eFwdReset) <> 0 THEN TellUserItsReset;
- IF BAND(userFlags, eAttention) <> 0 THEN
- BEGIN {the event is an attention message}
- myAttnCode := AttnCode; {Get the attention code.}
- CopyAttnMsg(AttnPtr, AttnSize, @myAttnData);
- {copy the attention }
- { message into our buffer}
- tempFlag := userFlags;
- tempCFlag := eAttention;
- BClr(LongInt(tempFlag), tempCFlag); {clear the flag}
- userFlags := tempFlag;
- {do something with the message}
- END;
- gReceivedAnEvent := TRUE;
- END;
- PopA5; {restore the current A5}
- END;
-
- _______________________________________________________________________________
-
- æKY .DSP…Driver…Routines
- æC ».DSP Driver Routines AppleTalk Manager
- _______________________________________________________________________________
-
- The .DSP driver implements the AppleTalk Data Stream Protocol (ADSP). You send
- commands to ADSP and obtain information about ADSP by executing the .DSP driver
- routines described in this section. Each routine is implemented as a call to the
- Device Manager’s PBControl function, as follows:
-
- FUNCTION PBControl (paramBlock: ParmBlkPtr; async: BOOLEAN) : OSErr;
-
- The paramBlock parameter is a pointer to the parameter block used by the
- PBControl function for .DSP routines, and the async parameter is a Boolean that
- specifies whether the function is to execute synchronously or asynchronously.
- Set the async parameter to TRUE to execute the function asynchronously.
-
- The parameter block is shown in “The .DSP Parameter Block” earlier in this
- chapter. The parameters used with each function are described in this section.
-
- For a general discussion of the use of ADSP, see “Using ADSP” earlier in this
- chapter.
-
- _______________________________________________________________________________
-
- æKY Establishing…&…Terminating…an…ADSP…Connection
- æC »Establishing & Terminating an ADSP Connection AppleTalk Manager
- _______________________________________________________________________________
-
- You can use the routines described in this section to
-
- • establish a connection end
-
- • set the values for parameters that control the behavior of a connection end
-
- • open a connection
-
- • assign an identification number to a connection end
-
- • close a connection end
-
- • eliminate a connection end
-
- dspInit
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word always dspInit
- ¨ 32 ccbRefNum word reference number of CCB
- Æ 34 ccbPtr long pointer to CCB
- Æ 38 userRoutine long pointer to routine to
- call on
-
-
-
- Æ 42 sendQSize word size in bytes of the
- send queue
- Æ 44 sendQueue long pointer to send queue
- Æ 48 recvQSize word size in bytes of the
- receive queue
- Æ 50 recvQueue long pointer to receive queue
- Æ 54 attnPtr long pointer to buffer
- for incoming
-
-
-
- ´ 58 localSocket byte DDP socket number for this
-
- end
-
- The dspInit routine establishes a connection end; that is, it assigns a specific
- socket for use by ADSP and initializes the variables that ADSP uses to maintain
- the connection. The dspInit routine does not open the connection end or
- establish a connection with a remote connection end; you must follow the dspInit
- routine with the dspOpen routine to perform those tasks. Use the dspCLInit
- routine to establish a connection listener. Use the dspRemove routine to
- eliminate a connection end.
-
- When you send bytes to a remote connection end, ADSP stores the bytes in a
- buffer called the send queue . Until the remote connection end acknowledges
- their receipt, ADSP keeps the bytes you sent in the send queue so that they are
- available to be retransmitted if necessary. When the local connection end
- receives bytes, it stores them in a buffer called the receive queue until you
- read them.
-
- You must allocate memory for the send and receive queues and for a buffer that
- holds incoming attention messages. You must also allocate a nonrelocatable block
- of memory for the CCB for this connection end.
-
- Note: When you call the dspInit routine, the memory that you allocate
- becomes
- the property of ADSP. You cannot write any data to this memory except by
- calling ADSP routines, and you must ensure that the memory remains
- locked until you call the dspRemove routine to eliminate the connection
- end.
-
- Fields
-
- ioResult The result of the routine. When you execute the
- routine
- asynchronously, the routine sets this
- parameter to 1 and
- returns a routine result of noErr as
- soon as the routine
- begins execution. When the routine
- completes execution, it
- sets the ioResult parameter to the
- actual result code.
-
- ioCRefNum The driver reference number. This parameter is
- returned by
- the OpenDriver function. You must
- specify this number
- every time you call the .DSP driver.
-
- csCode The routine selector, always equal to dspInit
- for this routine.
-
- ccbRefNum The CCB reference number. The dspInit routine
- returns this
- number. You must provide this number
- in all subsequent
- calls to this connection end.
-
- ccbPtr A pointer to the CCB that you allocated.
- The CCB is 242 bytes
- in size and is described in “The ADSP
- Connection Control
- Block” earlier in this chapter.
-
- userRoutine A pointer to a routine that is to be called each
- time the
- connection end receives an unsolicited
- connection event.
- Specify NIL for this parameter if you
- do not want to supply a
- user routine. Connection events and
- user routines are
- discussed in “Writing a User Routine
- for Connection
- Events” earlier in this chapter.
-
- sendQSize The size in bytes of the send queue. A queue size
- of 600 bytes
- should work well for most applications.
- If you are using
- ADSP to send a continuous flow of data,
- a larger data buffer
- improves performance. If your
- application is sending the
- user’s keystrokes, a smaller buffer
- should be adequate. The
- constant minDSPQueueSize indicates the
- minimum queue
- size that you can use.
-
- sendQueue A pointer to the send queue that you allocated.
-
- recvQSize The size in bytes of the receive queue. A queue
- size of 600
- bytes should work well for most
- applications. If you are using
- ADSP to receive a continuous flow of
- data, a larger data
- buffer improves performance. If your
- application is receiving
- a user’s keystrokes, a smaller buffer
- should be adequate. The
- constant minDSPQueueSize indicates the
- minimum queue
- size that you can use.
-
- recvQueue A pointer to the receive queue that you allocated.
-
- attnPtr A pointer to the attention-message buffer that
- you allocated.
- The attention-message buffer must be the
- size of the constant
- attnBufSize.
-
- localSocket The DDP socket number of the socket that you want
- ADSP to
- use for this connection end. Specify 0
- for this parameter to
- cause ADSP to assign the socket. In the
- latter case, ADSP
- returns the socket number when the
- dspInit routine
- completes execution.
-
- Result codes
- noErr 0 No error
- ddpSktErr –91 Error opening socket
- errDSPQueueSize –1274 Send or receive queue is too small
-
- dspOptions
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference
- number
- Æ 26 csCode word always
- dspOptions
- Æ 32 ccbRefNum word reference number of CCB
- Æ 34 sendBlocking word send-blocking threshold
- Æ 38 badSeqMax byte threshold to send
- retransmit advice
- Æ 39 useCheckSum byte use DDP checksum?
-
- The dspOptions routine allows you to set values for several parameters that
- affect the behavior of the local connection end. You can set the options for any
- established connection end, whether open or not.
-
- Fields
-
- ioResult The result of the routine. When you execute
- the routine
- asynchronously, the routine sets this
- parameter to 1 and
- returns a routine result of noErr as
- soon as the routine
- begins execution. When the routine
- completes execution, it
- sets the ioResult parameter to the
- actual result code.
-
- ioCRefNum The driver reference number. This parameter is
- returned by
- the OpenDriver function. You must
- specify this number
- every time you call the .DSP driver.
-
- csCode The routine selector, always equal to
- dspOptions for this
- routine.
-
- ccbRefNum The CCB reference number that was returned by the
- dspInit
- routine.
-
- sendBlocking The maximum number of bytes that may accumulate in
- the
- send queue before ADSP sends a packet
- to the remote
- connection end. ADSP sends a packet
- before the maximum
- number of bytes accumulates if the
- period specified by the
- send timer expires, if you execute the
- dspWrite routine with
- the flush parameter set to 1, or if a
- connection event
- requires that the local connection end
- send an
- acknowledgment packet to the remote
- connection end.
-
- You can set the sendBlocking parameter
- to any value from 1
- byte to the maximum size of a packet
- (572 bytes). If you set
- the sendBlocking parameter to 0, the
- current value for this
- parameter is not changed. The default
- value for the
- sendBlocking parameter is 16 bytes.
-
- badSeqMax The maximum number of out-of-sequence data packets
- that
- the local connection end can receive
- before requesting the
- remote connection end to retransmit the
- missing data.
- Because a connection end does not
- acknowledge the receipt of
- a data packet received out of sequence,
- the retransmit timer
- of the remote connection end will expire
- eventually and the
- connection end will retransmit the data.
- The badSeqMax
- parameter allows you to cause the data
- to be retransmitted
- before the retransmit timer of the
- remote connection end has
- expired.
-
- You can set the badSeqMax parameter to
- any value from 1 to
- 255. If you set the badSeqMax parameter
- to 0, the current
- value for this parameter is not changed.
- The default value for
- the badSeqMax parameter is 3.
-
- useCheckSum A flag specifying whether DDP should compute a checksum
- and include it in each packet that it
- sends to the remote
- connection end. Set this parameter to 1
- if you want DDP to
- use checksums or to 0 if you do not want
- DDP to use
- checksums. The default value for
- useCheckSum is 0.
-
- ADSP cannot include a checksum in a
- packet that has a short
- DDP header; that is, a packet being sent
- over LocalTalk to a
- remote socket that is on the same cable
- as the local socket.
- Note that the useCheckSum parameter
- affects only whether
- ADSP includes a checksum in a packet
- that it is sending. If
- ADSP receives a packet that includes a
- checksum, it validates
- the checksum regardless of the setting
- of the useCheckSum
- parameter.
-
- Result codes
- noErr 0 No error
- errRefNum –1280 Bad connection reference number
- _______________________________________________________________________________
-
- æKY Establishing…&…Terminating…an…ADSP…Connection…(cont'd)
- æC »Establishing & Terminating an ADSP Connection (cont'd) AppleTalk Manager
- _______________________________________________________________________________
-
- dspOpen
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word always dspOpen
- Æ 32 ccbRefNum word reference number of
- CCB
- ¨ 34 localCID word ID of this
- connection end
- ´ 36 remoteCID word ID of remote
- connection end
- ´ 38 remoteAddress long remote internet address
- Æ 42 filterAddress long filter for open
- connection requests
- ´ 46 sendSeq long initial send
- sequence number
- ´ 50 sendWindow word initial size of remote
- receive queue
- Æ 52 recvSeq long initial receive
- sequence number
- ´ 56 attnSendSeq long attention send
- sequence number
- Æ 60 attnRecvSeq long attention receive
- sequence number
- Æ 64 ocMode byte
- connection-opening mode
- Æ 65 ocInterval byte interval between
- open requests
- Æ 66 ocMaximum byte retries of
- open-connection request
-
- You use the ocMode field of the parameter block to specify the opening mode that
- the dspOpen routine is to use. The dspOpen routine puts a connection end into
- one of the four following opening modes:
-
- • The ocRequest mode, in which ADSP attempts to open a connection with the
- socket at the internet address you specify with the remoteAddress
- parameter. If
- the socket you specify as a remote address is a connection listener, it
- is possible
- that your application will receive a connection acknowledgment and
- request
- from a different address than the one to which you sent the
- open-connection
- request. You can use the filterAddress parameter to restrict the
- addresses with
- which you will accept a connection.
-
- The dspOpen routine completes execution in the ocRequest mode when one of
- the following occurs: ADSP establishes a connection, your connection end
- receives a connection denial from the remote connection end, your
- connection
- end denies the connection request returned by a connection listener, or
- ADSP
- cannot complete the connection within the maximum number of retries that
- you specified with the ocMaximum parameter.
-
- • The ocPassive mode, in which the connection end waits to receive an
- open-connection request from a remote connection end. You can use the
- filterAddress parameter to restrict the addresses from which you will
- accept a
- connection request.
-
- The dspOpen routine completes execution in the ocPassive mode when ADSP
- establishes a connection or when either connection end receives a
- connection
- denial.
-
- • The ocAccept mode, used by connection servers to complete an
- open-connection dialog. When a connection server is informed by its
- connection listener that the connection listener has received an
- open-connection request, the connection server calls the dspInit routine
- to
- establish a connection end and then calls the dspOpen routine in ocAccept
- mode to complete the connection. You must obtain the following parameters
- from the dspCLListen routine and provide them to the dspOpen routine:
- remoteAddress, remoteCID, sendSeq, sendWindow, and attnSendSeq.
- Connection listeners and connection servers are described in “Creating and
- Using a Connection Listener,” earlier in this chapter, and in
- “Establishing and
- Terminating an ADSP Connection ,” later in this chapter.
-
- The dspOpen routine completes execution in the ocAccept mode when ADSP
- establishes a connection or when either connection end receives a
- connection
- denial.
-
- • The ocEstablish mode, in which ADSP considers the connection end
- established
- and the connection state open. This mode is for use by clients that
- determine
- their connection-opening parameters without using ADSP or the .DSP driver
- to
- do so.
-
- You must first use the dspInit routine to establish a connection end and
- then
- execute the dspNewCID routine to obtain an identification number (ID) for
- the
- local connection end. You must then communicate with the remote connection
- end to send it the local connection ID and to determine the values of the
- following parameters: remoteAddress, remoteCID, sendSeq, sendWindow,
- recvSeq, attnSendSeq, and attnRecvSeq. Only then can you execute the
- dspOpen
- routine in the ocEstablish mode.
-
- The dspOpen routine completes execution in the ocEstablish mode
- immediately.
-
- The use of parameters by the dspOpen routine depends on the mode in which
- the routine is executed, as follows:
-
- ocRequest ocPassive ocAccept
- ocEstablish
-
- ¨ ioResult ¨ ioResult ¨ ioResult
- ¨ ioResult
- Æ ioCRefNum Æ ioCRefNum Æ ioCRefNum Æ ioCRefNum
- Æ csCode Æ csCode Æ csCode
- Æ csCode
- Æ ccbRefNum Æ ccbRefNum Æ ccbRefNum Æ ccbRefNum
- ¨ localCID ¨ localCID ¨ localCID
- — localCID
- ¨ remoteCID ¨ remoteCID Æ remoteCID Æ
- remoteCID
- Æ remoteAddress ¨ remoteAddress Æ remoteAddress Æ remoteAddress
- Æ filterAddress Æ filterAddress — filterAddress —
- filterAddress
- ¨ sendSeq ¨ sendSeq Æ sendSeq
- Æ sendSeq
- ¨ sendWindow ¨ sendWindow Æ sendWindow Æ sendWindow
- — recvSeq — recvSeq — recvSeq
- Æ recvSeq
- ¨ attnSendSeq ¨ attnSendSeq Æ attnSendSeq Æ
- attnSendSeq
- — attnRecvSeq — attnRecvSeq — attnRecvSeq Æ
- attnRecvSeq
- Æ ocMode Æ ocMode Æ ocMode
- Æ ocMode
- Æ ocInterval Æ ocInterval Æ ocInterval —
- ocInterval
- Æ ocMaximum Æ ocMaximum Æ ocMaximum — ocMaximum
-
- Key: Æ input ¨ output — not used
-
- Fields
-
- ioResult The result of the routine. When you execute the
- routine
- asynchronously, the routine sets this
- parameter to 1 and
- returns a routine result of noErr as soon
- as the routine begins
- execution. When the routine completes
- execution, it sets the
- ioResult parameter to the actual result
- code.
-
- ioCRefNum The driver reference number. This parameter is returned by
- the
- OpenDriver function. You must specify this
- number every time
- you call the .DSP driver.
-
- csCode The routine selector, always equal to dspOpen for
- this routine.
-
- ccbRefNum The CCB reference number that was returned by the dspInit
- routine for the connection end that you want
- to use.
-
- localCID The identification number of the local connection
- end. This
- number is assigned by ADSP when the
- connection is opened.
- ADSP includes this number in every packet
- sent to a remote
- connection end. Before you call the dspOpen
- routine in
- ocEstablish mode, you must call the
- dspNewCID routine to
- cause ADSP to assign this value.
-
- remoteCID The identification number of the remote connection end.
- This
- parameter is returned by the dspOpen routine
- in the ocRequest
- and ocPassive modes. A connection server
- must provide this
- number to the dspOpen routine when the
- server executes the
- routine in ocAccept mode; in this case, the
- connection server
- obtains the remoteCID value from the
- dspCLListen routine.
- You must provide the remoteCID value to the
- dspOpen routine
- when you use the routine in ocEstablish
- mode.
-
- remoteAddress The internet address of the remote socket with which you
- wish
- to establish communications. This address
- consists of a 2-byte
- network number, a 1-byte node ID, and a
- 1-byte socket number.
- You must provide this parameter when you call
- the dspOpen
- routine in the ocRequest or ocEstablish
- modes. This parameter
- is returned by the dspOpen routine when you
- call the routine in
- the ocPassive mode. When you call the dspOpen
- routine in the
- ocAccept mode, you must use the value for the
- remoteAddress
- parameter that was returned by the
- dspCLListen routine.
-
- filterAddress The internet address of the socket from which you will
- accept a
- connection request. The address consists of
- three fields: a 2-byte
- network number, a 1-byte node ID, and a
- 1-byte socket number.
- Specify 0 for any of these fields for which
- you wish to impose no
- restrictions. If you specify a filter address
- of $00082500, for
- example, the connection end accepts a
- connection request from
- any socket at node $25 of network $0008. Set
- the filterAddress
- parameter equal to the remoteAddress
- parameter to accept a
- connection only with the socket to which you
- sent a connection
- request.
-
- When you execute the dspOpen routine in the
- ocPassive mode,
- you can receive a connection request from any
- ADSP
- connection end on the internet. When you
- execute the dspOpen
- routine in the ocRequest mode, your
- connection end can
- receive a connection request acknowledgment
- from an address
- different from the one you specified in the
- remoteAddress
- parameter only if the remote address you
- specified was that of a
- connection listener. In either case, you can
- use the filterAddress
- parameter to avoid acknowledging unwanted
- connection
- requests.
-
- When you execute the dspOpen routine in the
- ocAccept mode,
- your connection listener has already received
- and decided to
- accept the connection request. You can
- specify a filter address for
- a connection listener with the dspCLListen
- routine. A
- connection server can use the dspCLDeny
- routine to deny a
- connection request that was accepted by its
- connection listener.
-
- You cannot use the filter address when you
- execute the dspOpen
- routine in ocEstablish mode.
-
- sendSeq The sequence number of the first byte that the local
- connection
- end will send to the remote connection end.
- ADSP uses this
- number to coordinate communications and to
- check for errors.
- ADSP returns a value for the sendSeq
- parameter when you
- execute the dspOpen routine in the ocRequest
- or ocPassive
- modes. When you execute the dspOpen routine
- in the ocAccept
- mode, you must specify the value for the
- sendSeq parameter
- that was returned by the dspCLListen routine.
- You must
- provide the value for this parameter when you
- execute the
- dspOpen routine in the ocEstablish mode.
-
- sendWindow The sequence number of the last byte that the remote
- connection
- end has buffer space to receive. ADSP uses
- this number to
- coordinate communications and to check for
- errors. ADSP
- returns a value for the sendWindow parameter
- when you
- execute the dspOpen routine in the ocRequest
- or ocPassive
- modes. When you execute the dspOpen routine in
- the ocAccept
- mode, you must specify the value for the
- sendWindow
- parameter that was returned by the dspCLListen
- routine. You
- must provide the value for this parameter when
- you execute the
- dspOpen routine in the ocEstablish mode.
-
- recvSeq The sequence number of the next byte that the local
- connection
- end expects to receive. ADSP uses this number
- to coordinate
- communications and to check for errors. You
- must provide the
- value for this parameter when you execute the
- dspOpen routine
- in the ocEstablish mode. The dspOpen routine
- does not use this
- parameter when you execute it in any other
- mode.
-
- attnSendSeq The sequence number of the next attention packet that the
- local
- connection end will transmit. ADSP uses this
- number to
- coordinate communications and to check for
- errors. ADSP
- returns a value for the attnSendSeq parameter
- when you execute
- the dspOpen routine in the ocRequest or
- ocPassive modes. When
- you execute the dspOpen routine in the ocAccept
- mode, you
- must specify the value for the attnSendSeq
- parameter that was
- returned by the dspCLListen routine. You must
- provide the
- value for this parameter when you execute the
- dspOpen routine
- in the ocEstablish mode.
-
- attnRecvSeq The sequence number of the next attention packet that the
- local
- connection end expects to receive. ADSP uses
- this number to
- coordinate communications and to check for
- errors. You must
- provide the value for this parameter when you
- execute the
- dspOpen routine in the ocEstablish mode. The
- dspOpen routine
- does not use this parameter when you execute it
- in any other
- mode.
-
- ocMode The mode in which the dspOpen routine is to operate, as
- follows:
-
- Mode Value Meaning
- ocRequest 1 ADSP
- attempts to open a connection
-
-
-
-
-
-
-
- ocPassive 2 The
- connection end waits to receive
-
-
-
-
-
- ocAccept 3 The
- connection server accepts and
-
-
-
-
-
-
-
-
-
- ocEstablish 4 ADSP
- considers the connection
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ocInterval The period between transmissions of open-connection
- requests.
- If the remote connection end does not
- acknowledge or deny an
- open-connection request, ADSP retransmits the
- request after a
- time period specified by this parameter. The
- time period used by
- ADSP is (ocInterval ¥ 10) ticks; or
- (ocInterval / 6) seconds. For
- example, if you set the ocInterval parameter
- to 3, the time period
- between retransmissions is 30 ticks (1/2
- second). You can set the
- ocInterval parameter to any value from 1 (1/6
- second) to 180 (30
- seconds). If you specify 0 for the ocInterval
- parameter, ADSP uses
- the default value of 6 (1 second).
-
- You must provide a value for the ocInterval
- parameter when
- you execute the dspOpen routine in the
- ocRequest, ocPassive, or
- ocAccept modes. The dspOpen routine does not
- use this
- parameter when you execute it in the
- ocEstablish mode.
-
- ocMaximum The maximum number of times to retransmit an
- open-connection request before ADSP terminates
- execution of
- the dspOpen routine. If you specify 0 for the
- ocMaximum
- parameter, ADSP uses the default value of 3.
- If you specify 255
- for the ocMaximum parameter, ADSP retransmits
- the
- open-connection request indefinitely until the
- remote
- connection end either acknowledges or denies
- the request.
-
- You must provide a value for the ocMaximum
- parameter when
- you execute the dspOpen routine in the
- ocRequest, ocPassive, or
- ocAccept modes. The dspOpen routine does not
- use this
- parameter when you execute it in the
- ocEstablish mode.
-
- Result codes
- noErr 0 No error
- errOpenDenied –1273 Open request denied by recepient
- errOpening –1277 Attempt to open connection
- failed
- errState –1278 Connection end must be
- closed
- errAborted –1279 Request aborted by dspRemove
- or dspClose
- routine
- errRefNum –1280 Bad connection reference number
-
- dspNewCID
-
- Parameter block
- ¨ 16 ioResult word result code
-
- Æ 24 ioCRefNum word driver reference
- number
- Æ 26 csCode word always
- dspNewCID
- Æ 32 ccbRefNum word reference number
- of CCB
- ¨ 34 newCID word ID of new
- connection
-
- The dspNewCID routine causes ADSP to assign an ID to a connection end without
- opening the connection end or attempting to establish a connection with a remote
- connection end. Use this routine only if you implement your own protocol to
- establish communications with a remote connection end. You must first use the
- dspInit routine to establish a connection end. Next, you must call the dspNewCID
- routine to obtain a connection-end ID. Then you must establish communication
- with a remote connection end and pass the ID to the remote connection end.
- Finally, you must call the dspOpen routine in ocEstablish mode to cause ADSP to
- open the connection. See the description of the dspOpen routine for more
- information on establishing a connection in this fashion.
-
- The ioResult parameter returns the result of the routine. If you call the
- routine asynchronously, the routine sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The ioCRefNum parameter is the driver reference number returned by
- the OpenDriver function. You must specify this number every time you call the
- .DSP driver. The csCode parameter is the routine selector; it is always
- dspNewCID for this routine. The ccbRefNum parameter is the CCB reference number
- that was returned by the dspInit routine. The newCID parameter is the
- connection-end ID returned by this routine. You must provide this number to the
- client of the remote connection end so that it can use it for the remoteCID
- parameter when it calls the dspOpen routine.
-
- Result codes
- noErr 0 No error
- errState –1278 Connection is not closed
- errRefNum –1280 Bad connection reference number
-
- dspClose
-
- Parameter block
- ¨ 16 ioResult word result
- code
- Æ 24 ioCRefNum word driver
- reference number
- Æ 26 csCode word always
- dspClose
- Æ 32 ccbRefNum word reference
- number of CCB
- Æ 34 abort byte
- abort send requests if not 0
-
- The dspClose routine closes the connection end. The connection end is still
- established; that is, ADSP retains ownership of the CCB, send queue, receive
- queue, and attention-message buffer. You can continue to read bytes from the
- receive queue after you have called the dspClose routine. Use the dspRemove
- routine instead of the dspClose routine if you are through reading bytes from
- the receive queue and want to release the memory associated with the connection
- end. The dspClose routine does not return an error if you call it for a
- connection end that is already closed.
-
- The ioResult parameter returns the result of the routine. If you call the
- routine asynchronously, the routine sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The ioCRefNum parameter is the driver reference number returned by
- the OpenDriver function. You must specify this number every time you call the
- .DSP driver. The csCode parameter is the routine selector; it is always dspClose
- for this routine. The ccbRefNum parameter is the CCB reference number that was
- returned by the dspInit routine. If the abort parameter is nonzero, ADSP cancels
- any outstanding requests to send data packets (such as the dspAttention routine)
- and discards all data in the send queue. If the abort parameter is 0, ADSP does
- not close the connection end until all of the data in the send queue and all
- outstanding attention messages have been sent and acknowledged.
-
- Result codes
- noErr 0 No error
- errRefNum –1280 Bad connection reference number
-
- dspRemove
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference
- number
- Æ 26 csCode word always
- dspRemove
- Æ 32 ccbRefNum word reference number of
- CCB
- Æ 34 abort byte abort
- connection if not 0
-
- The dspRemove routine closes any open connection and eliminates the connection
- end; that is, ADSP no longer retains control of the CCB, send queue, receive
- queue, and attention-message buffer. You cannot continue to read bytes from the
- receive queue after you have called the dspRemove routine. After you call the
- dspRemove routine, you can release all of the memory you allocated for the
- connection end if you do not intend to reopen the connection end.
-
- The ioResult parameter returns the result of the routine. If you call the
- routine asynchronously, the routine sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The ioCRefNum parameter is the driver reference number returned by
- the OpenDriver function. You must specify this number every time you call the
- .DSP driver. The csCode parameter is the routine selector, always dspRemove for
- this routine. The ccbRefNum parameter is the CCB reference number that was
- returned by the dspInit routine. If the abort parameter is nonzero, ADSP cancels
- any outstanding requests to send data packets (such as the dspAttention routine)
- and discards all data in the send queue. If the abort parameter is 0, ADSP does
- not close the connection end until all of the data in the send queue has been
- sent and acknowledged.
-
- Result codes
- noErr 0 No error
- errRefNum –1280 Bad connection reference number
- _______________________________________________________________________________
-
- æKY Establishing…&…Terminating…an…ADSP…Connection…Listener
- æC »Establishing & Terminating an ADSP Connection Listener AppleTalk Manager
- _______________________________________________________________________________
-
- A connection listener is a special kind of connection end that listens for
- open-connection requests from remote connection ends. Connection listeners are
- used by connection servers; that is, programs that assign a socket for the local
- connection end only after they receive a connection request from a remote
- connection end. A single connection listener can receive connection requests
- from any number of remote connection ends.
-
- You can use the routines in this section to
-
- • establish a connection listener
-
- • cause the connection listener to wait for a connection request
-
- • deny a connection request
-
- • close and eliminate a connection listener
-
- dspCLInit
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word always dspCLInit
- ¨ 32 ccbRefNum word reference number of CCB
- Æ 34 ccbPtr long pointer to CCB
- ´ 58 localSocket byte local DDP socket
- number
-
- The dspCLInit routine establishes a connection listener; that is, it assigns a
- specific socket for use by ADSP and initializes the variables that ADSP uses to
- maintain a connection listener. The dspCLInit routine does not cause the
- connection listener to listen for connection requests; you must follow the
- dspCLInit routine with the dspCLListen routine to activate the connection
- listener. Use the dspInit routine to establish a connection end that is not a
- connection listener. Use the dspCLRemove routine to eliminate a connection
- listener.
-
- The ioResult parameter returns the result of the routine. If you call the
- routine asynchronously, the routine sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The ioCRefNum parameter is the driver reference number returned by
- the OpenDriver function. You must specify this number every time you call the
- .DSP driver. The csCode parameter is the routine selector, always dspCLInit for
- this routine. The dspCLInit routine returns the ccbRefNum parameter, which is
- the CCB reference number. You must provide this number in all subsequent
- dspCLListen and dspCLRemove calls to this connection listener.
-
- You must allocate memory for a CCB before you call the dspCLInit routine. The
- ccbPtr parameter is a pointer to the CCB that you allocated. The CCB is 242
- bytes and is described in “The ADSP Connection Control Block” earlier in this
- chapter.
-
- The localSocket parameter is the DDP socket number of the socket that you want
- ADSP to use for this connection end. Specify 0 for this parameter to cause ADSP
- to assign the socket. In the latter case, ADSP returns the socket number when
- the dspCLInit routine completes execution.
-
- Result codes
- noErr 0 No error
- ddpSktErr –91 Error opening socket
-
- dspCLListen
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word always dspCLListen
- Æ 32 ccbRefNum word reference number of CCB
- ¨ 36 remoteCID word ID of remote connection end
- ¨ 38 remoteAddress long remote internet address
- Æ 42 filterAddress long filter for open-connection
- requests
- ¨ 46 sendSeq long initial send sequence
- number
- ¨ 50 sendWindow word initial size of remote receive
- queue
- ¨ 56 attnSendSeq long attention send sequence
- number
-
- The dspCLListen routine causes a connection listener to listen for connection
- requests. You must have already used the dspCLInit routine to establish a
- connection listener before using the dspCLListen routine. The dspCLListen
- routine is used only by connection servers.
-
- When ADSP receives an open-connection request from a socket that satisfies the
- address requirements of the filterAddress parameter, it returns values for the
- remoteCID, remoteAddress, sendSeq, sendWindow, and attnSendSeq parameters and
- completes execution of the dspCLListen routine. You must then either accept the
- open-connection request by calling the dspOpen routine in the ocAccept mode or
- deny the request by calling the dspCLDeny routine.
-
- You can call the dspCLListen routine several times, specifying the same
- connection listener. For example, if you wanted to accept connections from any
- or all of three different addresses, you could call the dspCLListen routine
- three times with a different value for the filterAddress parameter each time.
- Note that you must execute the dspCLListen routine asynchronously to take
- advantage of this feature.
-
- Fields
-
- ioResult The result of the routine. When you execute the
- routine
- asynchronously, the routine sets this
- parameter to 1 and
- returns a routine result of noErr as
- soon as the routine begins
- execution. When the routine completes
- execution, it sets the
- ioResult parameter to the actual result
- code.
-
- ioCRefNum The driver reference number. This parameter is returned
- by
- the OpenDriver function. You must
- specify this number
- every time you call the .DSP driver.
-
- csCode The routine selector, always dspCLListen for
- this routine.
-
- ccbRefNum The CCB reference number that was returned by the
- dspCLInit
- routine.
-
- remoteCID The identification number of the remote connection
- end. You
- must pass this value to the dspOpen
- routine when you open
- the connection or to the dspCLDeny
- routine when you deny
- the connection request.
-
- remoteAddress The internet address of the remote socket that sent a
- request to
- open a connection. This address consists
- of a 2-byte network
- number, a 1byte node ID, and a 1-byte
- socket number. You
- must pass this value to the dspOpen
- routine when you open
- the connection or to the dspCLDeny
- routine when you deny
- the connection request.
-
- filterAddress The internet address of the socket from which you
- will accept
- a connection request. The address
- consists of three fields: a
- 2-byte network number, a 1-byte node ID,
- and a 1-byte socket
- number. Specify 0 for any of these fields
- for which you wish to
- impose no restrictions. If you specify a
- filter address of
- $00082500, for example, the connection
- listener accepts a
- connection request from any socket at
- node $25 of network
- $0008.
-
- sendSeq The sequence number of the first byte that the
- local connection
- end will send to the remote connection
- end. ADSP uses this
- number to coordinate communications and to
- check for
- errors. You must pass this value to the
- dspOpen routine when
- you open the connection.
-
- sendWindow The sequence number of the last byte that the remote
- connection end has buffer space to
- receive. ADSP uses this
- number to coordinate communications and to
- check for
- errors. You must pass this value to the
- dspOpen routine
- when you open the connection.
-
- attnSendSeq The sequence number of the next attention packet that
- the
- local connection end will transmit. ADSP
- uses this number to
- coordinate communications and to check for
- errors. You must
- pass this value to the dspOpen routine
- when you open the
- connection.
-
- Result codes
- noErr 0 No error
- errState –1278 Not a connection listener
- errAborted –1279 Request aborted by the dspRemove routine
- errRefNum –1280 Bad connection reference number
-
- dspCLDeny
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word always dspCLDeny
- Æ 32 ccbRefNum word reference number of CCB
- Æ 36 remoteCID word ID of remote connection
- end
- Æ 38 remoteAddress long remote internet address
-
- The dspCLDeny routine is used by a connection server to inform a remote
- connection end that its request to open a connection cannot be honored.
-
- The ioResult parameter returns the result of the routine. If you call the
- routine asynchronously, the routine sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The ioCRefNum parameter is the driver reference number returned by
- the OpenDriver function. You must specify this number every time you call the
- .DSP driver. The csCode parameter is the routine selector; it is always
- dspCLDeny for this routine. The ccbRefNum parameter is the CCB reference number
- for the connection listener that received the connection request. This number is
- returned by the dspCLInit routine when you establish a connection listener. The
- remoteCID and remoteAddress parameters specify the address and ID of the remote
- connection end. These parameters are returned by the dspCLListen routine.
-
- Result codes
- noErr 0 No error
- errState –1278 Not a connection listener
- errAborted –1279 Request aborted by the dspRemove routine
- errRefNum –1280 Bad connection reference number
-
- dspCLRemove
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word always dspCLRemove
- Æ 32 ccbRefNum word reference number of CCB
- Æ 34 abort byte abort
- connection listener if not 0
-
- The dspCLRemove routine closes a connection end used as a connection listener.
- You can release the memory you allocated for the CCB if you do not intend to
- reopen the connection end.
-
- The ioResult parameter returns the result of the routine. If you call the
- routine asynchronously, the routine sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The ioCRefNum parameter is the driver reference number returned by
- the OpenDriver function. You must specify this number every time you call the
- .DSP driver. The csCode parameter is the routine selector, always dspCLRemove
- for this routine. The ccbRefNum parameter is the CCB reference number that was
- returned by the dspCLInit routine. If the abort parameter is nonzero, ADSP
- cancels any outstanding requests to send packets (such as the dspCLDeny
- routine).
-
- Result codes
- noErr 0 No error
- errRefNum –1280 Bad connection reference number
- _______________________________________________________________________________
-
- æKY Maintaining…an…ADSP…Connection
- æC »Maintaining an ADSP Connection AppleTalk Manager
- _______________________________________________________________________________
-
- Once you have established a connection end and opened a connection, you must be
- able to send and receive data over the connection. You can use the routines in
- this section to
-
- • determine the status of a connection
-
- • read bytes from the connection end’s receive queue
-
- • write bytes to the connection end’s send queue and transmit them to the
- remote
- connection end
-
- • send an attention message to the remote connection end
-
- • discard all data that has been sent but not yet delivered, and reset the
- connection
-
- dspStatus
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word always dspStatus
- Æ 32 ccbRefNum word reference number of CCB
- ¨ 34 statusCCB long pointer to CCB
- ¨ 38 sendQPending word bytes waiting to be sent
- or
-
-
- ¨ 40 sendQFree word available send queue
- in bytes
- ¨ 42 recvQPending word bytes waiting to be read
- from queue
- ¨ 44 recvQFree word available receive
- queue in bytes
-
- The dspStatus routine returns the number of bytes waiting to be read and sent
- and the space available in the send and receive queues. This routine also
- returns a pointer to the CCB, which contains information about the state of the
- connection end and about connection events received by the connection end. The
- CCB is described in “The ADSP Connection Control Block” earlier in this chapter.
-
- The ioResult parameter returns the result of the routine. If you call the
- routine asynchronously, the routine sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The ioCRefNum parameter is the driver reference number returned by
- the OpenDriver function. You must specify this number every time you call the
- .DSP driver. The csCode parameter is the routine selector; it is always
- dspStatus for this routine. The ccbRefNum parameter is the CCB reference number
- that was returned by the dspInit routine. The statusCCB parameter returns a
- pointer to the CCB.
-
- The sendQPending parameter indicates the number of bytes of data in the send
- queue, including 1 byte for each end-of-message (EOM) indicator in the send
- queue. (ADSP counts 1 byte for each EOM, even though no actual data corresponds
- to the EOM indicator.) The send queue contains all data that has been sent to
- ADSP for transmission and that has not yet been acknowledged. Some of the data
- in the send queue might have already been transmitted, but ADSP retains it in
- the send queue until the remote connection end acknowledges its receipt in case
- the data has to be retransmitted. The sendQFree parameter indicates the number
- of bytes available in the send queue for additional data.
-
- The recvQPending parameter indicates the number of bytes in the receive queue,
- including one byte for each EOM if the EOM bit is set in an ADSP packet header.
- The receive queue contains all of the data that has been received by the
- connection end but not yet read by the connection end’s client. The recvQFree
- parameter indicates the number of bytes available in the receive queue for
- additional data.
-
- Result codes
- noErr 0 No error
- errRefNum –1280 Bad connection reference number
-
- dspRead
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference
- number
- Æ 26 csCode word always
- dspRead
- Æ 32 ccbRefNum word reference number of
- CCB
- Æ 34 reqCount word requested
- number of bytes
- ¨ 36 actCount word actual number
- of bytes read
- Æ 38 dataPtr long pointer to
- data buffer
- ¨ 42 eom byte 1 if
- end-of-message; 0 otherwise
-
- The dspRead routine reads bytes from the connection end’s receive queue and
- places them in a buffer that you specify. You can continue to read bytes as long
- as data is in the receive queue, even after you have called the dspClose routine
- or after the remote connection end has called the dspClose or dspRemove
- routines. The dspRead routine completes execution when it has read the number of
- bytes you specify or when it encounters an end-of-message (that is, the last
- byte of data in an ADSP packet that has the EOM bit set in the packet header).
-
- You can call the dspStatus routine to determine the number of bytes remaining to
- be read from the read queue, or you can continue to call the dspRead routine
- until the actCount and eom parameters both return 0.
-
- The ioResult parameter returns the result of the routine. If you call the
- routine asynchronously, the routine sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The ioCRefNum parameter is the driver reference number returned by
- the OpenDriver function. You must specify this number every time you call the
- .DSP driver. The csCode parameter is the routine selector; it is always dspRead
- for this routine. The ccbRefNum parameter is the CCB reference number that was
- returned by the dspInit routine.
-
- You specify the number of bytes to read with the reqCount parameter, and you use
- the dataPtr parameter to provide a pointer to the buffer into which ADSP should
- place the data. ADSP returns the actual number of bytes read in the actCount
- parameter. If the last byte read constitutes an EOM, ADSP sets the eom parameter
-
- to 1.
-
- If either end closes the connection before you call the dspRead routine, the
- command reads whatever data is available and returns the actual amount of data
- read in the actCount parameter. If the connection is closed and there is no data
- in the receive queue, the dspRead routine returns the noErr result code with the
- actCount parameter set to 0 and the eom parameter set to 0.
-
- Result codes
- noErr 0 No error
- errFwdReset –1275 Read terminated by forward reset
- errState –1278 State isn’t open, closing, or
- closed
- errAborted –1279 Request aborted by dspRemove or
- dspClose routine
- errRefNum –1280 Bad connection reference number
-
- dspWrite
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word always dspWrite
- Æ 32 ccbRefNum word reference number of CCB
- Æ 34 reqCount word requested number of
- bytes
- ¨ 36 actCount word actual number of
- bytes written
- Æ 38 dataPtr long pointer to data
- buffer
- Æ 42 eom byte 1 if end of
- message; 0 otherwise
- Æ 43 flush byte 1 to send
- data now; 0 otherwise
-
- The dspWrite routine writes bytes into the connection end’s send queue. The send
- queue contains all data that has been sent to ADSP for transmission and that has
- not yet been acknowledged. Some of the data in the send queue might have already
- been transmitted, but ADSP retains it in the send queue until the remote
- connection end acknowledges its receipt in case the data has to be
- retransmitted. The dspWrite routine completes execution when it has copied all
- of the data from the data buffer into the ADSP send queue.
-
- ADSP transmits the data in the send queue when the remote connection end has
- room to accept the data and one of the following conditions occurs:
-
- • You call the dspWrite routine with the flush parameter set to a nonzero
- number.
-
- • The number of bytes in the send queue equals or exceeds the blocking
- factor.
- (You use the sendBlocking parameter to the dspOptions routine to set the
- blocking factor.)
-
- • The send timer expires.
-
- • A connection event requires that the local connection end send an
- acknowledgment packet to the remote connection end.
-
- The ioResult parameter returns the result of the routine. If you call the
- routine asynchronously, the routine sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The ioCRefNum parameter is the driver reference number returned by
- the OpenDriver function. You must specify this number every time you call the
- .DSP driver. The csCode parameter is the routine selector; it is always dspWrite
- for this routine. The ccbRefNum parameter is the CCB reference number that was
- returned by the dspInit routine.
-
- You specify the number of bytes to write with the reqCount parameter, and you
- use the dataPtr parameter to provide a pointer to the buffer from which ADSP
- should read the data. The dspWrite routine returns the actual number of bytes
- written in the actCount parameter. If the last byte written constitutes an EOM,
- set the eom parameter to 1. You can also set the reqCount parameter to 0 and the
- eom parameter to 1 to indicate that the last byte you sent the previous time you
- called the dspWrite routine was the end of the message. The high-order bits of
- the eom parameter are reserved for use by ADSP; you must leave these bits equal
- to 0.
-
- You can set the reqCount parameter to a value larger than the size of the send
- queue. If you do so, the dspWrite routine writes as much data as it can into the
- send queue, sends the data and waits for acknowledgment, and then writes more
- data into the send queue until it has written the amount of data you requested.
- In this case, the routine does not complete execution until it has finished
- writing all of the data into the send queue.
-
- Set the flush parameter to 1 to cause ADSP to immediately transmit any data in
- the send queue that has not already been transmitted. Set the flush parameter to
- 0 to allow data to accumulate in the send queue until another condition occurs
- that causes data to be transmitted. The high-order bits of the flush parameter
- are reserved for use by ADSP; you must leave these bits equal to 0.
-
- Result codes
- noErr 0 No error
- errState –1278 Connection is not open
- errAborted –1279 Request aborted by dspRemove or dspClose
- routine
- errRefNum –1280 Bad connection reference number
-
- dspAttention
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word always dspAttention
- Æ 32 ccbRefNum word reference number of CCB
- Æ 34 attnCode word client attention code
- Æ 36 attnSize word size of attention
- data in bytes
- Æ 38 attnData long pointer to
- attention data
-
- The dspAttention routine sends an attention code and an attention message to the
- remote connection end. Attention codes and attention messages can have any
- meaning that your application and the application at the remote connection end
- both recognize. The purpose of attention codes and messages is to allow clients
- of ADSP to send messages outside the normal data stream. For example, if a
- connection end on a mainframe computer is connected to several connection ends
- in Macintosh computers being used as remote terminals, the mainframe computer
- might wish to inform the remote terminals that all connections will be
- terminated in ten minutes. The mainframe application could send an attention
- message to each of the remote terminals informing them of this fact, and the
- terminal emulation programs in the Macintosh computers could then display an
- alert message on the screen so that the users could prepare to shut down.
-
- The ioResult parameter returns the result of the routine. If you call the
- routine asynchronously, the routine sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The ioCRefNum parameter is the driver reference number returned by
- the OpenDriver function. You must specify this number every time you call the
- .DSP driver. The csCode parameter is the routine selector; it is always
- dspAttention for this routine. The ccbRefNum parameter is the CCB reference
- number that was returned by the dspInit routine.
-
- The attnCode parameter is the attention code that you wish to send to the remote
- connection end. You can use any value from $0000 through $EFFF for the attention
- code. The values $F000 through $FFFF are reserved for use by ADSP. The attnSize
- parameter is the size in bytes of the attention message you wish to send, and
- the attnData parameter provides a pointer to the attention message. The
- attention message can be any size from 0 through 570 bytes. There are no
- restrictions on the content of the attention message.
-
- Result codes
- noErr 0 No error
- errAttention –1276 Attention message too long
- errState –1278 Connection is not open
- errAborted –1279 Request aborted by dspRemove or dspClose
- routine
- errRefNum –1280 Bad connection reference number
-
- dspReset
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word always dspReset
- Æ 32 ccbRefNum word reference number of CCB
-
- The dspReset routine causes ADSP to discard all data in the send queue, all data
- in transit to the remote connection end, and all data in the remote connection
- end’s receive queue that the client has not yet read. This process is known as a
- forward reset. ADSP then resynchronizes the connection. You can determine that
- your connection end has received a forward reset and has discarded all data in
- the receive queue by checking the eFwdReset flag in the userFlags field of the
- CCB. The CCB is described in “The ADSP Connection Control Block” earlier in this
- chapter.
-
- The ioResult parameter returns the result of the routine. If you call the
- routine asynchronously, the routine sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The ioCRefNum parameter is the driver reference number returned by
- the OpenDriver function. You must specify this number every time you call the
- .DSP driver. The csCode parameter is the routine selector; it is always dspReset
- for this routine. The ccbRefNum parameter is the CCB reference number that was
- returned by the dspInit routine.
-
- Result codes
- noErr 0 No error
- errState –1278 Connection is not open
- errAborted –1279 Request aborted by dspRemove or dspClose
- routine
- errRefNum –1280 Bad connection reference number
- _______________________________________________________________________________
-
- æKY The….ENET…Driver…Volume…VI
- æC »The .ENET Driver Volume VI AppleTalk Manager
- _______________________________________________________________________________
-
- The .ENET driver is normally called by the AppleTalk Manager through the
- AppleTalk connection file for EtherTalk when the user has selected EtherTalk
- from the Network control panel. You can write your own protocol stack or
- application that uses the .ENET driver directly, rather than through AppleTalk.
- This section describes how to open the .ENET driver, how to send data to it
- directly for transmission over the Ethernet network, and how to write a protocol
- handler to receive data from the network.
-
- The system .ENET driver locates and opens the drivers for installed NuBus®
- Ethernet cards. For each Ethernet NuBus card, the .ENET driver searches the open
- resource files for a driver with a resource type of 'enet' and a resource ID
- equal to the board ID of the NuBus card. If it doesn't find such a driver
- resource, it then looks for a driver named .ENET in the slot resources in the
- ROM of the NuBus card. See Designing Cards and Drivers for the Macntosh Family
- for discussions of NuBus board IDs and slot resources.
-
- _______________________________________________________________________________
-
- æKY Providing…Your…Own…Ethernet…Driver
- æC »Providing Your Own Ethernet Driver AppleTalk Manager
- _______________________________________________________________________________
-
- If you write an Ethernet driver for use with your own Ethernet NuBus card, you
- should provide the features and functions described in this chapter. You can
- store the driver in the firmware of the NuBus card as described in Designing
- Cards and Drivers for the Macntosh Family and in the Device Manager chapter of
- Inside Macintosh , Volume V, or you can provide a RAM-based driver as described
- in the Device Manager chapter of Inside Macintosh , Volume II. If you place your
- Ethernet driver in the ROM of the NuBus card, you must name the driver .ENET. If
- you provide a RAM-based driver, you must give it a resource type of 'enet' and a
- resource ID equal to the board ID of your NuBus card. The 'enet' resource type
- is identical to the 'DRVR' resource type described in the Device Manager chapter
- of Volume II.
-
- Note: You must not name a RAM-based driver “.ENET,” because doing so would
- replace the system .ENET driver.
-
- If you write an Ethernet driver for use with a non-NuBus network interface (such
- as an Ethernet card for the Macintosh SE/30 or an Ethernet connection through
- the SCSI port), you should provide the features and functions described in this
- chapter for the .ENET driver and should name your driver .ENET0. If you do so,
- any software written to use the .ENET driver should work with your driver.
-
- _______________________________________________________________________________
-
- æKY Changing…the…Ethernet…Hardware…Address
- æC »Changing the Ethernet Hardware Address AppleTalk Manager
- _______________________________________________________________________________
-
- Each Ethernet NuBus card or other Ethernet hardware interface device contains a
- unique 6-byte hardware address assigned by the manufacturer of the device. The
- .ENET driver normally uses this address to determine whether to receive a
- packet. To change the hardware address for your node, place in the System file a
- resource of type 'eadr' with a resource ID equal to the slot number of the
- Ethernet NuBus card. If the Ethernet device is not a NuBus card (it might be a
- slot card in a Macintosh SE/30, for example), use a resource ID of 0.
-
- The 'eadr' resource consists only of a 6-byte number. Do not use the broadcast
- address or a multicast address for this number. (The broadcast address is
- $FF-FF-FF-FF-FF-FF. A multicast address is any Ethernet address in which the
- low-order bit of the high-order byte is set to 1.) When you open the .ENET
- driver, it looks for an 'eadr' resource. If it finds one, the driver substitutes
- the number in this resource for the Ethernet hardware address and uses it until
- the driver is closed or reset.
-
- Note: To avoid address collisions, you should never arbitrarily change the
- Ethernet hardware address. This feature should be used only by a system
- administrator who can keep track of all the Ethernet addresses in the system.
-
- _______________________________________________________________________________
-
- æKY Opening…the….ENET…Driver
- æC »Opening the .ENET Driver AppleTalk Manager
- _______________________________________________________________________________
-
- Before you use the OpenSlot function to open the .ENET driver, you must
- determine which NuBus slots contain EtherTalk cards. The OpenSlot function is
- described in the Device Manager chapter of Volume V. Use the SGetTypesRsrc
- function described in the Slot Manager chapter of this volume to determine which
- NuBus slots contain EtherTalk cards. To find EtherTalk NuBus cards, use the
- value catNetwork in the field spCategory of the GetTypesRsrc function parameter
- block, and use the value typEtherNet in the field spCType. If you cannot find
- any EtherTalk NuBus cards, you should also attempt to open the .ENET0 driver in
- case a non-NuBus EtherTalk card is attached to the system. You should provide a
- user interface that allows the user to select a specific EtherTalk card in the
- case that more than one is present.
-
- Listing 32-7 illustrates the use of the GetTypesRsrc function and the OpenSlot
- function to open the .ENET driver.
-
- ¿ Listing 32-7 Finding an EtherTalk card and opening the .ENET driver
-
- VAR
- mySBlk: SpBlock;
- myPBRec: ParamBlockRec;
- myErr: OSErr;
- Found: Integer;
- EnetStr: Str15;
- Enet0Str: Str15;
- myRefNum: Integer;
-
- BEGIN
- Found := 0; {assume no sResource found}
- EnetStr := '.ENET';
- Enet0Str := '.ENET0';
-
- REPEAT
- WITH mySBlk DO
- BEGIN
- spParamData := 1; {include search of disabled resources. }
- { Start searching from spSlot and search }
- { the slots above it as well.}
- spCategory := catNetwork;
- spCType := typeEtherNet;
- spDrvrSW := 0;
- spDrvrHW := 0;
- spTBMask := 3; {match only Category and CType fields}
- spSlot := 0; {start search from here}
- spID := 0; {start search from here}
- spExtDev := 0; {ID of the external device}
- END;
- myErr := SGetTypeSRsrc(@mySBlk);
- IF myErr = noErr THEN
- {We found an sResource match, save it for later. }
- BEGIN
- Found := Found + 1;
- SaveSInfo(@mySBlk);
- END;
- UNTIL myErr = smNoMoresRsrcs;
-
- IF Found > 1 THEN
- BEGIN
- {If you found more than one sResource, put up a dialog box }
- { and let the user choose one. If any of the sResources you }
- { found were disabled, let the user know they are not available. }
- DisplaySInfo(@mySBLk);
- END;
-
- IF Found <> 0 THEN
- BEGIN
- WITH myPBRec DO
- BEGIN
- ioCompletion := NIL;
- ioNamePtr := @EnetStr;
- ioMix := NIL; {reserved}
- ioFlags := 0; {single device sResource}
- ioSlot := mySBlk.spSlot;
- ioID := mySBlk.spID;
- END;
- myErr := OpenSlot(@myPBRec, FALSE); {go open this}
- END
- ELSE myErr := OpenDriver(Enet0Str, myRefNum);
- IF myErr <> NoErr THEN DoError(myErr);
- END;
- _______________________________________________________________________________
-
- æKY Using…a…Write-Data…Structure…to…Transmit…Ethernet…Data
- æC »Using a Write-Data Structure to Transmit Ethernet Data AppleTalk Manager
- _______________________________________________________________________________
-
- When you use the EWrite function to send data to the .ENET driver for
- transmission over the Ethernet network, you provide a pointer to a write-data
- structure (Figure 32-5). A write-data structure contains a series of pairs of
- length words and pointers. Each pair indicates the length and location of a
- portion of the data that constitutes the packet to be sent over the network. The
- first length-pointer pair points to a 14-byte header block, which starts with
- the destination node hardware address. Note that this is not the AppleTalk
- address, but is the hardware address of the destination node. If you are calling
- the .ENET driver directly, you must obtain the Ethernet address of the
- destination node yourself; AppleTalk cannot provide it.
-
- The next 6 bytes of the header block are reserved for use by the .ENET driver.
- These bytes are followed by the 2-byte Ethernet protocol type. Data may follow
- the header block; all other length-pointer pairs point to data. The write-data
- structure terminates with a 0 word.
-
- ¿ Figure 32-5 An Ethernet write-data structure ø
-
- When you first open the .ENET driver, it allocates a 768-byte buffer that it
- uses for transmitting data packets. This buffer is large enough to hold the
- largest EtherTalk packet, which is 621 bytes in size. If you want to transmit
- data packets larger than 768 bytes, call the ESetGeneral function. The .ENET
- driver then allocates a large enough data buffer to send packets up to 1514
- bytes in size.
-
- Listing 32-8 defines an Ethernet write-data structure and then calls the EWrite
- function to send a data packet over Ethernet.
-
- ¿ Listing 32-8 Sending a data packet over Ethernet
-
- CONST
- size1 = 100;
- size2 = 333;
-
- TYPE
- WDS = RECORD {write-data structure}
- length : Integer; {length of nth entry}
- aptr : Ptr; {pointer to nth entry}
- END;
-
- VAR
- myWDS: ARRAY [1..4] OF WDS;
- myPB: EParamBlock; {.ENET parameter block}
- wheader: ARRAY [1..14] OF Byte;
- stuff1: ARRAY [1..size1] OF Byte;
- stuff2: ARRAY [1..size2] OF Byte;
- myErr: OSErr;
-
- BEGIN
- {set up the write header}
- wheader[1] := $02; {dest node ID}
- wheader[2] := $60;
- wheader[3] := $8C;
- wheader[4] := $04;
- wheader[5] := $05;
- wheader[6] := $06;
- {bytes 7-12 are reserved}
- wheader[13] := $08; {protocol type}
- wheader[14] := $00;
-
- myWDS[1].length := 14; {the write header is always 14 bytes}
- myWDS[1].aptr := @wheader;
- myWDS[2].length := size1;
- myWDS[2].aptr := @stuff1;
- myWDS[3].length := size2;
- myWDS[3].aptr := @stuff2;
- myWDS[4].length := 0; {terminator}
-
- myPB.ePointer := @myWDS; {pointer to write data structure}
- myErr := EWrite(@myPB, FALSE); {send something}
- IF myErr <> NoErr THEN DoError(myErr);
- END;
- _______________________________________________________________________________
-
- æKY Using…the…Default…Ethernet…Protocol…Handler…to…Read…Data
- æC »Using the Default Ethernet Protocol Handler to Read Data AppleTalk Manager
- _______________________________________________________________________________
-
- When the EtherTalk Nubus card or other Ethernet hardware receives a data packet,
- it generates an interrupt to the CPU. The interrupt handler in ROM determines
- the source of the interrupt and calls the .ENET driver. The .ENET driver reads
- the packet header to determine the protocol type of the data packet and checks
- to see if any client has specified that protocol type in a call to the EAttachPH
- function. If so, the client either specified a NIL pointer to a protocol
- handler, or the client provided its own protocol handler. If the client
- specified a NIL pointer, the .ENET driver uses its default protocol handler to
- read the data. If no one has specified that protocol type in a call to the
- EAttachPH function, the .ENET driver discards the data. The EAttachPH function
- is described in “Attaching and Detaching an Ethernet Protocol Handler” later in
- this chapter.
-
- The default protocol handler checks for an ERead function pending execution and
- places the entire packet—including the packet header—into the buffer specified
- by that function. The function returns the number of bytes actually read. If the
- packet is larger than the data buffer, the ERead function places as much of the
- packet as will fit into the buffer and returns the buf2SmallErr result code.
-
- Call the ERead function asynchronously to await the next data packet. When the
- .ENET driver receives the data packet, it completes execution of the ERead
- function and calls your completion routine. Your completion routine should call
- the ERead function again so that an ERead function is always pending execution.
- If the .ENET driver receives a data packet with a protocol type for which you
- specified the default protocol handler while no ERead function is pending, the
- .ENET driver discards the packet.
-
- You can have several asynchronous calls to the ERead function pending execution
- simultaneously as long as you use different buffers and a different parameter
- block for each call.
-
- Listing 32-9 calls the EAttachPH function to specify that the .ENET driver
- should use the default protocol handler to process protocol type MyPType. The
- listing includes a completion routine that processes a received data packet and
- then makes an asynchronous call to the ERead function to await the next incoming
- data packet.
- In practice, you should call the EAttachPH function very early, during your
- program initialization sequence, if possible. As soon as the connection is
- established and you are expecting data, you should call the ERead function
- asynchronously. When the .ENET driver receives a packet, it then calls your
- completion routine, which should process the packet and queue another
- asynchronous call to the ERead function to await the next packet.
-
- ¿ Listing 32-9 Using the default Ethernet protocol handler to read data
-
- CONST
- BigBytes = 8888;
-
- VAR
- myPB: EParamBlock;
- EPBPtr: EParamBlkPtr;
- APtr: Ptr;
- myErr: OSErr;
-
- PROCEDURE MyCompRoutine;
-
- VAR
- myErr: OSErr;
-
- BEGIN
- {If this gets called, an incoming packet with the specified protocol }
- { type is here.}
-
- ProcessData(BigBytes, APtr); {do something with the data}
- IF EPBPtr^.ioResult <> noErr THEN DoError(myErr);
-
- {call ERead again}
- WITH EPBPtr^ DO {set up ERead parameters}
- BEGIN
- ioCompletion := @MyCompRoutine; {pointer to completion routine}
- eProtType := 77; {protocol type}
- ePointer := APtr; {pointer to read data area}
- eBuffSize := BigBytes; {size of read data area}
- END;
- myErr := ERead(EPBPtr, TRUE); {call ERead to wait for }
- { the next packet}
- IF myErr <> noErr THEN DoError(myErr);
- END;
-
- BEGIN {main}
- EPBPtr := @myPB;
- WITH EPBPtr^ DO {set up EAttachPH parameters}
- BEGIN
- eProtType := 77; {protocol type}
- ePointer := NIL; {use default protocol handler}
- END;
- myErr := EAttachPH(EPBPtr, FALSE); {tell .ENET about this }
- { protocol handler}
- IF myErr <> NoErr THEN DoError(myErr);
-
- APtr := NewPtr(BigBytes);
- WITH EPBPtr^ DO {set up ERead parameters}
- BEGIN
- ioCompletion := @MyCompRoutine; {pointer to completion routine}
- eProtType := 77; {protocol type}
- ePointer := APtr; {pointer to read data area}
- eBuffSize := BigBytes; {size of read data area}
- END;
- myErr := ERead(EPBPtr, TRUE); {wait for your packet and }
- { then read it}
- IF myErr <> noErr THEN DoError(myErr);
-
- {application-defined tasks}
-
- END; {main}
-
- _______________________________________________________________________________
-
- æKY Using…Your…Own…Ethernet…Protocol…Handler…to…Read…Data
- æC »Using Your Own Ethernet Protocol Handler to Read Data AppleTalk Manager
- _______________________________________________________________________________
-
- If a client of the .ENET driver has used the EAttachPH function to provide a
- pointer to its own protocol handler, the .ENET driver calls that protocol
- handler, which must in turn call the .ENET driver’s ReadPacket and ReadRest
- routines to read the data. Your protocol handler calls the .ENET driver’s
- ReadPacket and ReadRest routines in essentially the same way as you call the
- .MPP drivers ReadPacket and ReadRest routines (see the AppleTalk Manager chapter
- of Volume II). The following sections describe how the .ENET driver calls a
- custom protocol handler and the ReadPacket and ReadRest routines.
-
- Note: Because an Ethernet protocol handler must read from and write to the
- CPU’s registers, you cannot write a protocol handler in Pascal.
-
- _______________________________________________________________________________
-
- æKY How…the….ENET…Driver…Calls…Your…Protocol…Handler
- æC »How the .ENET Driver Calls Your Protocol Handler AppleTalk Manager
- _______________________________________________________________________________
-
- You can provide an Ethernet protocol handler for a particular protocol type and
- use the EAttachPH function to attach it to the .ENET driver. When the driver
- receives an Ethernet packet, it reads the packet header into an internal buffer,
- reads the protocol type, and calls the protocol handler for that protocol type.
- The CPU is in interrupt mode, and the registers are used as follows:
-
- Registers on call to Ethernet protocol handler
-
- A0 Reserved for internal use by the .ENET driver. You
- must
- preserve this register until after the ReadRest
- routine has
- completed execution.
-
- A1 Reserved for internal use by the .ENET driver. You
- must
- preserve this register until after the ReadRest
- routine has
- completed execution.
-
- A2 Free for your use.
-
- A3 Pointer to first byte past data-link header bytes
- (the first byte after
- the 2-byte protocol-type field).
-
- A4 Pointer to the ReadPacket routine. The ReadRest
- routine starts 2
- bytes after the start of the ReadPacket
- routine.
-
- A5 Free for your use until after the ReadRest routine
- has completed
- execution.
-
- D0 Free for your use.
-
- D1 Number of bytes in the Ethernet packet left to be
- read (that is, the
- number of bytes following the Ethernet header).
-
- D2 Free for your use.
-
- D3 Free for your use.
-
- If your protocol handler processes more than one protocol type, you can read the
- protocol-type field in the data-link header to determine the protocol type of
- the packet. The protocol-type field starts 2 bytes before the address pointed to
- by the A3 register.
-
- Note: The source address starts 8 bytes before the address pointed to by the
- A3
- register, and the destination address starts 14 bytes before the address
- pointed to
- by the A3 register.
-
- If you know that the packet contains pad bytes and you know the actual size of
- the data, you can reduce the number in the D1 register by the number of pad
- bytes so that the .ENET driver can keep accurate track of the number of bytes
- remaining to be read. In all other circumstances, you should not change the
- value in the D1 register.
-
- After you have called the ReadRest routine, you can use registers A0 through A3
- and D0 through D3 for your own use, but you must preserve all other registers.
- You cannot depend on having access to your application global variables.
-
- _______________________________________________________________________________
-
- æKY How…Your…Protocol…Handler…Calls…the….ENET…Driver
- æC »How Your Protocol Handler Calls the .ENET Driver AppleTalk Manager
- _______________________________________________________________________________
-
- Your protocol handler must call the .ENET driver routines ReadPacket and
- ReadRest to read the incoming data packet. You may call the ReadPacket routine
- as many times as you like to read the data piece by piece into one or more data
- buffers, but you must always use the ReadRest routine to read the final piece of
- the data packet. The ReadRest routine restores the machine state (the stack
- pointers, status register, and so forth) and checks for error conditions.
-
- Before you call the ReadPacket routine, you must allocate memory for a data
- buffer and place a pointer to the buffer in the A3 register. You place the
- number of bytes you want to read in the D3 register. You must not request more
- bytes than remain in the data packet.
-
- To call the ReadPacket routine, execute a JSR instruction to the address in the
- A4 register. The ReadPacket routine uses the registers as follows:
-
- Registers on entry to the ReadPacket routine
-
- A3 Pointer to a buffer to hold the data you want to
- read
-
- D3 Number of bytes to read; must be nonzero
-
- Registers on exit from the ReadPacket routine
-
- A0 Unchanged
-
- A1 Unchanged
-
- A2 Unchanged
-
- A3 First byte after the last byte read into buffer
-
- D0 Changed
-
- D1 Number of bytes left to be read
-
- D2 Unchanged
-
- D3 Equals 0 if requested number of bytes were read,
- nonzero if error
-
- The ReadPacket routine indicates an error by clearing to 0 the zero (z) flag in
- the status register. If the ReadPacket routine returns an error, you must
- terminate execution of your protocol handler with an RTS instruction without
- calling ReadPacket again or calling ReadRest at all.
-
- Call the ReadRest routine to read the last portion of the data packet, or call
- it after you have read all the data with ReadPacket routines and before you do
- any other processing or terminate execution. You must provide in the A3 register
- a pointer to a data buffer and must indicate in the D3 register the size of the
- data buffer. If you have already read all of the data with calls to the
- ReadPacket routine, you can specify a buffer of size 0.
-
- † Warning: If you do not call the ReadRest routine after your last call
- to the
- ReadPacket routine, the system will crash. Ê
-
- To call the ReadRest routine, execu† te a JSR instruction to an address 2 bytes
- past the address in the A4 register. The ReadRest routine uses the registers as
- follows:
-
- Registers on entry to the ReadRest routine
-
- A3 Pointer to a buffer to hold the data you want to
- read
-
- D3 Size of the buffer (word length); may be 0
-
- Registers on exit from the ReadRest routine
-
- A0 Unchanged
-
- A1 Unchanged
-
- A2 Unchanged
-
- A3 Pointer to first byte after the last byte read
- into buffer
-
- D0 Changed
-
- D1 Changed
-
- D2 Unchanged
-
- D3 Equals 0 if requested number of bytes were read;
- less than 0 if
- more data was left than would fit in buffer
- (extra data equals –D3
- bytes); greater than 0 if less data was left
- than the size of the
- buffer (extra buffer space equals D3 bytes)
-
- The ReadRest routine indicates an error by clearing to 0 the zero (z) flag in
- the status register.
-
- You must terminate execution of your protocol handler with an RTS instruction
- whether or not the ReadRest routine returns an error.
-
- _______________________________________________________________________________
-
- æKY .ENET…Driver…Routines
- æC ».ENET Driver Routines AppleTalk Manager
- _______________________________________________________________________________
-
- An application that uses AppleTalk Manager routines for network communications
- can talk to whatever AppleTalk network the user has selected through the Network
- control panel. However, you can choose to write an application that talks only
- to Ethernet; in this case, your application has to address the Ethernet driver
- directly. This section describes the functions that you can use to control the
- .ENET driver, the Ethernet driver provided with system software version 7.0.
- Each .ENET driver function is of the following form:
-
- FUNCTION Efunc (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- The thePBptr parameter is a pointer to the .ENET parameter block and the async
- parameter is a Boolean that specifies whether the function is to be executed
- synchronously or asynchronously. Set the async parameter to TRUE to execute the
- function asynchronously.
-
- The .ENET parameter block is defined as follows:
-
- TYPE EParamBlock =
- packed record
- qLink: QElemPtr; {next queue entry}
- qType: Integer; {queue type}
- ioTrap: Integer; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OsErr; {result code}
- ioNamePtr: StringPtr; {driver name}
- ioVRefNum: Integer; {volume reference number}
- ioRefNum: Integer; {driver reference number}
- csCode: Integer; {primary command code}
-
- CASE Integer OF
- ENetWrite,
- ENetAttachPH,
- ENetDetachPH,
- ENetRead,
- ENetRdCancel,
- ENetGetInfo,
- ENetSetGeneral:
- (
- eProtType: Integer; {Ethernet protocol type}
- ePointer: Ptr; {pointer; use depends on }
- { function}
- eBuffSize Integer; {buffer size}
- eDataSize Integer {number of bytes read}
- );
-
- ENetAddMulti,
- ENetDelMulti:
- (
- eMultiAddr: ARRAY [0..5] of Char {Multicast address}
- );
- END;
-
- The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and ioVRefNum fields are filled
- in by the Device Manager; your application should not have to set or read these
- fields. The ioResult field returns the result of the function. If you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The ioCompletion field is a pointer to a completion routine that you
- can provide; the Device Manager calls your completion routine when it completes
- execution of the function. If you are not providing a completion routine,
- specify NIL for this field. You must obtain the driver reference number from the
- OpenDriver function and use it for the ioRefNum field.
-
- The csCode field specifies the command to be executed; the MPW Pascal interface
- fills in this field for you. The .ENET driver accepts the following constants as
- routine selectors:
-
- CONST {.ENET driver routine selectors}
- ENetSetGeneral = 253; {Set "general" mode}
- ENetGetInfo = 252; {Get info}
- ENetRdCancel = 251; {Cancel read}
- ENetRead = 250; {Read}
- ENetWrite = 249; {Write}
- ENetDetachPH = 248; {Detach protocol handler}
- ENetAttachPH = 247; {Attach protocol handler}
- ENetAddMulti = 246; {Add a multicast address}
- ENetDelMulti = 245; {Delete a multicast address}
-
- The remaining parameters are used only for specific functions; all of these
- parameters are described in the following sections.
-
- For a general discussion of the use of the Ethernet driver, see “The .ENET
- Driver” earlier in this chapter.
-
- _______________________________________________________________________________
-
- æKY Attaching…and…Detaching…an…Ethernet…Protocol…Handler
- æC »Attaching and Detaching an Ethernet Protocol Handler AppleTalk Manager
- _______________________________________________________________________________
-
- The functions in this section allow you to attach a protocol handler to the
- .ENET driver, to specify which protocol handler the .ENET driver is to use for
- each protocol type, and to detach a protocol handler that you previously
- attached. The section “Using Your Own Ethernet Protocol Handler to Read Data,”
- earlier in this chapter, describes how to write and use Ethernet protocol
- handlers.
-
- FUNCTION EAttachPH (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always ENetAttachPH
- Æ 28 eProtType word Ethernet protocol type
- Æ 30 ePointer long pointer to protocol
- handler
-
- The EAttachPH function serves two purposes: you can use it to attach to the
- .ENET driver your own protocol handler for a specific protocol type, or you can
- use it to specify that the .ENET driver should use the default protocol handler
- for a particular protocol type. If you attach your own protocol handler, the
- .ENET driver calls that protocol handler each time it receives a packet with the
- protocol type you specified. If you specify that the .ENET driver should use the
- default protocol handler, then you can use the ERead command to read packets
- with that protocol type.
-
- The ioResult parameter returns the result of the function. If you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The csCode parameter is a routine selector; it is always equal to
- ENetAttachPH for this function.
-
- You specify the protocol type in the eProtType parameter and provide a pointer
- to the protocol handler in the ePointer parameter. If you specify NIL for the
- ePointer parameter, then the .ENET driver uses the default protocol handler for
- that protocol type. Specify 0 for the eProtType parameter to attach a protocol
- handler for the IEEE 802.3 protocol, which uses protocol types 0 through $5DC.
-
- Note: The LAP Manager calls the EAttachPH function with a protocol type of 0
- and thus receives all 802.3 protocol packets. Instead of using the EAttachPH
- function to install a protocol handler for an 802.3 Ethernet protocol type,
- you
- should use the L802Attach routine. In the case of an 802.3 protocol packet,
- the
- .ENET driver passes the packet to the LAP Manager 802.2 protocol handler. If
- the
- packet has the protocol type you specified with the L802Attach routine, the
- 802.2
- protocol handler passes the packet on to your protocol handler. For more
- information about IEEE 802.2 and 802.3 protocols, see “The LAP Manager 802.2
- Protocol” earlier in this chapter.
-
- Result codes
- noErr 0 No error
- LAPProtErr –94 Protocol handler is already attached or
- node’s protocol
- table is full
-
- FUNCTION EDetachPH (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always
- ENetDetachPH
- Æ 28 eProtType word Ethernet protocol
- type
-
- The EDetachPH function detaches a protocol handler from the .ENET driver. Once
- you have removed a protocol type from the node’s protocol table with this
- function, the .ENET driver no longer delivers packets with that protocol type.
- You specify the protocol type in the eProtType parameter.
-
- The ioResult parameter returns the result of the function. If you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The csCode parameter is a routine selector that is set automatically
- for you by the MPW interface; it is always equal to ENetDetachPH for this
- function.
-
- When you call the EDetachPH function, any pending calls to the ERead function
- terminate with the reqAborted result code.
-
- Result codes
- noErr 0 No error
- LAPProtErr –94 No protocol handler is attached
- _______________________________________________________________________________
-
- æKY Writing…and…Reading…Ethernet…Packets
- æC »Writing and Reading Ethernet Packets AppleTalk Manager
- _______________________________________________________________________________
-
- The functions in this section send and read Ethernet packets, cancel execution
- of a read operation, return information about the .ENET driver, and switch the
- .ENET driver from limited-transmission mode to general-transmission mode.
-
- FUNCTION EWrite (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always ENetWrite
- Æ 30 ePointer long pointer to write-data
- structure
-
- The EWrite function uses the .ENET driver to send a data packet over Ethernet.
- You must first prepare a write-data structure that specifies the destination
- address and the protocol type and contains the data that you want to send. You
- place a pointer to the write-data structure in the ePointer parameter. If you
- want to send a packet larger than 768 bytes, you must first call the ESetGeneral
- function to put the .ENET driver in general transmission mode. If the size of
- the packet you provide is less than 60 bytes, the driver adds pad bytes to the
- packet. Write-data structures are described in “Using a Write-Data Structure to
- Transmit Ethernet Data” earlier in this chapter.
-
- The ioResult parameter returns the result of the function. If you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The csCode parameter is a routine selector that is set automatically
- for you by the MPW interface; it is always equal to ENetWrite for this function.
-
-
- Result codes
- noErr 0 No error
- eLenErr –92 Packet too large or first entry of
- the
- write-data-structure did
- not contain the full
- 14-byte
- header
- excessCollsns –95 Hardware error
-
- FUNCTION ERead (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always ENetRead
- Æ 28 eProtType word Ethernet protocol
- type
- Æ 30 ePointer long pointer to data
- buffer
- Æ 34 eBuffSize word size of data buffer
- ¨ 36 eDataSize word number of bytes read
-
- The ERead function uses the default protocol handler to read a data packet and
- place it in a data buffer. You can use the ERead function to read packets of a
- particular protocol type only after you have used the EAttachPH function to
- specify a NIL pointer to the protocol handler for that protocol type.
-
- The ioResult parameter returns the result of the function. If you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The csCode parameter is the routine selector, automatically set by
- the MPW interface. It is always ENetRead for this function.
-
- The eProtType parameter specifies the protocol type of the packet you want to
- read. The ePointer parameter is a pointer to the data buffer into which you want
- to read data, and the eBuffSize parameter indicates the size of the data buffer.
- If you are expecting EtherTalk data packets, the buffer should be at least 621
- bytes in size; if you are expecting general Ethernet data packets, the buffer
- should be at least 1514 bytes in size.
-
- The ERead function places the entire packet, including the packet header, into
- your buffer. The function returns in the eDataSize parameter the number of bytes
- actually read. If the packet is larger than the data buffer, the ERead function
- places as much of the packet as will fit into the buffer and returns the
- buf2SmallErr result code.
-
- Call the ERead function asynchronously to await the next data packet. When the
- .ENET driver receives the data packet, it completes execution of the ERead
- function and calls your completion routine. If the .ENET driver receives a data
- packet with a protocol type for which you specified the default protocol handler
- while no ERead command is pending, the driver discards the data packet.
-
- You can have several asynchronous calls to the ERead function pending execution
- simultaneously, as long as you use a different parameter block for each call.
-
- Result codes
- noErr 0 No error
- LAPProtErr –94 Protocol not attached or protocol
- handler pointer
- was not 0
- buf2SmallErr –3101 Packet too large for buffer; partial
- data returned
- reqAborted –1105 ERdCancel or EDetachPH function
- called
-
- FUNCTION ERdCancel (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always ENetRdCancel
- Æ 30 ePointer long pointer to ERead
- parameter block
-
- The ERdCancel function cancels execution of a specific call to the ERead
- function. You must have called the ERead function asynchronously to use the
- ERdCancel function. You specify in the ePointer parameter a pointer to the
- parameter block that you used when you called the ERead function.
-
- The ioResult parameter returns the result of the function. If you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The csCode parameter is the routine selector, automatically set by
- the MPW interface. It is always ENetRdCancel for this function.
-
- When you call the ERdCancel function, the pending ERead function that you cancel
- receives the reqAborted result code.
-
- Result codes
- noErr 0 No error
- cbNotFound –1102 ERead not active
-
- FUNCTION EGetInfo (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always ENetGetInfo
- Æ 30 ePointer long pointer to buffer
- Æ 34 eBuffSize word size of buffer
-
- The EGetInfo function returns information about the .ENET driver. Before calling
- this function, you must allocate a data buffer of at least 18 bytes. Put a
- pointer to the buffer in the ePointer parameter and the size of the buffer in
- the eBuffSize parameter.
-
- The EGetInfo function places the following information in the data buffer:
-
- Bytes Information
-
- 1–6 Ethernet address of the node on which the driver is
- installed
- 7–10 Number of times the receive queue has overflowed
- 11–14 Number of data transmission operations that have timed
- out
- 15–18 Number of packets received that contain an incorrect
- address
-
- An incorrect Ethernet address is one that is neither the broadcast address, a
- multicast address for which this node is registered, nor the node’s data link
- address. A node could receive an incorrect Ethernet address due to a hardware or
- software error.
-
- The ioResult parameter returns the result of the function. If you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The csCode parameter is the routine selector, automatically set by
- the MPW interface. It is always ENetGetInfo for this function.
-
- Result code
- noErr 0 No error
-
- FUNCTION ESetGeneral (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always ENetSetGeneral
-
- The ESetGeneral function switches the .ENET driver from limited-transmission
- mode to general-transmission mode. In limited-transmission mode, the .ENET
- driver allocates a write-data buffer of 768 bytes. This buffer size is more than
- sufficient to hold an EtherTalk data packet, which can be no larger than 621
- bytes. In general-transmission mode, the .ENET driver can transmit an Ethernet
- data packet of up to 1514 bytes.
-
- The ioResult parameter returns the result of the function. If you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The csCode parameter is the routine selector, automatically set by
- the MPW interface. It is always ENetSetGeneral for this function.
-
- There is no command to switch the .ENET driver from general-transmission mode to
- limited-transmission mode. To switch back to limited-transmission mode, you have
- to reset the driver by restarting the computer.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Insufficient memory in heap
- _______________________________________________________________________________
-
- æKY Adding…and…Removing…Ethernet…Multicast…Addresses
- æC »Adding and Removing Ethernet Multicast Addresses AppleTalk Manager
- _______________________________________________________________________________
-
- The functions in this section add or delete Ethernet multicast addresses for a
- particular node. A multicast address is an Ethernet address for which the node
- accepts packets just as it does for its permanently assigned Ethernet hardware
- address. In a multicast address, the low-order bit of the high-order byte is set
- to 1. Each node can have any number of multicast addresses, and any number of
- nodes can have the same multicast address. The purpose of a multicast address is
- to allow a group of Ethernet nodes to receive the same transmission
- simultaneously, in a fashion similar to the AppleTalk broadcast service.
-
- FUNCTION EAddMulti (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
-
- Æ 26 csCode word always
- ENetAddMulti
- Æ 28 eMultiAddr 6 bytes multicast
- address
-
- The EAddMulti function adds a multicast address to the node on which the .ENET
- driver is running.
-
- You must provide (in the eMultiAddr parameter) the multicast address that you
- want to use. Each time a client of the .ENET driver calls the EAddMulti function
- for a particular multicast address, the driver increments a counter for that
- multicast address. Each time a client of the .ENET driver calls the EDelMulti
- function, the driver decrements the counter for that address. As long as the
- count for a multicast address is equal to or greater than 1, the .ENET driver
- accepts packets directed to that multicast address. Therefore, if any client of
- the .ENET driver in the node has called the EAddMulti function for a particular
- multicast address, the driver receives packets delivered to that address.
-
- The ioResult parameter returns the result of the function. If you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The csCode parameter is the routine selector, automatically set by
- the MPW interface. It is always ENetAddMulti for this function.
-
- Result codes
- noErr 0 No error
- eMultiErr –91 Invalid address or table is full
-
- FUNCTION EDelMulti (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always
- ENetDelMulti
- Æ 28 eMultiAddr 6 bytes multicast address
-
- The EDelMulti function decrements the counter kept by the .ENET driver for a
- particular multicast address. Each time a client of the .ENET driver calls the
- EAddMulti function, the driver increments a counter for the multicast address
- specified by the eMultiAddr parameter. Each time a client of the .ENET driver
- calls the EDelMulti function, the driver decrements the counter for the address
- specified by the eMultiAddr parameter. As long as the count for a multicast
- address is equal to or greater than 1, the .ENET driver accepts packets directed
- to that multicast address. When the count for an address equals 0, the driver
- removes that address from the list of multicast addresses that it accepts.
-
- Note: Because more than one client of the .ENET driver might be using a
- particular multicast address, you should call the EDelMulti function only
- once for
- each time you called the EAddMulti function.
-
- The ioResult parameter returns the result of the function. If you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and it changes the field to the actual result code when it completes
- execution. The csCode parameter is the routine selector, automatically set by
- the MPW interface. It is always ENetDelMulti for this function.
-
- Result codes
- noErr 0 No error
- eMultiErr –91' Address not found
- _______________________________________________________________________________
-
- æKY Summary…of…the…Appletalk…Manager…Volume…VI
- æC »Summary of the Appletalk Manager Volume VI AppleTalk Manager
- _______________________________________________________________________________
-
- Click the arrow in the lower-right corner of this window to see the summary
- sections of the constants, datatypes, and routines for the AppleTalk Manager.
-
- _______________________________________________________________________________
-
- æKY Appletalk…Manager…Constants
- æC »Appletalk Manager Constants AppleTalk Manager
- _______________________________________________________________________________
-
- const
- {AppleTalk transitions}
- ATTransOpen = 0; {open transition}
- ATTransClose = 2; {prepare-to-close transition}
- ATTransClosePrep = 3; {permission-to-close transition}
- ATTransCancelClose = 4; {cancel-close transition}
-
- {.XPP driver routine selector}
- xCall = 246;
-
- {.XPP driver routine selector subcodes}
- zipGetLocalZones = 5;
- zipGetZoneList = 6;
- zipGetMyZone = 7;
-
- {ADSP routine selectors}
- dspInit = 255; {create a new connection end}
- dspRemove = 254; {remove a connection end}
- dspOpen = 253; {open a connection}
- dspClose = 252; {close a connection}
- dspCLInit = 251; {create a connection listener}
- dspCLRemove = 250; {remove a connection listener}
- dspCLListen = 249; {post a listener request}
- dspCLDeny = 248; {deny an open-connection request}
- dspStatus = 247; {get status of connection end}
- dspRead = 246; {read data from the connection}
- dspWrite = 245; {write data on the connection}
- dspAttention = 244; {send an attention message}
- dspOptions = 243; {set connection end options}
- dspReset = 242; {forward reset the connection}
- dspNewCID = 241; {generate a cid for a connection end}
-
- {ADSP connection opening modes}
- ocRequest = 1; {request a connection with remote}
- ocPassive = 2; {wait for a connection request from }
- { remote connection end}
- ocAccept = 3; {accept request as delivered by
- listener}
- ocEstablish = 4; {consider connection to be open}
-
- {ADSP connection end states}
- sListening = 1; {for connection listeners}
- sPassive = 2; {waiting for a connection request
- from }
- { remote connection end}
- sOpening = 3; {requesting a connection with remote}
- sOpen = 4; {connection is open}
- sClosing = 5; {connection is being torn down}
- sClosed = 6; {connection end state is closed}
-
- {ADSP client event flags}
- eClosed = $80; {received connection closed advice}
- eTearDown = $40; {closed due to broken connection}
- eAttention = $20; {received attention message}
- eFwdReset = $10; {received forward reset advice}
-
- {miscellaneous ADSP constants}
- attnBufSize = 570; {size of client attention buffer}
- minDSPQueueSize = 100; {minimum size of receive or send
- queue}
-
- {.ENET driver values}
- catNetwork = 4; {spCategory for EtherTalk NB card}
- typeEtherNet = 1; {spCType for EtherTalk NB card}
-
- {LAP Manager values}
- LAPMgrCall = 2; {Offset to LAP routines}
- LAddAEQ = 23; {LAPAddATQ routine selector}
- LRmvAEQ = 24; {LAPRmvATQ routine selector}
-
- {.ENET driver routine selectors}
- ENetSetGeneral = 253; {Set "general" mode}
- ENetGetInfo = 252; {Get info}
- ENetRdCancel = 251; {Cancel read}
- ENetRead = 250; {Read}
- ENetWrite = 249; {Write}
- ENetDetachPH = 248; {Detach protocol handler}
- ENetAttachPH = 247; {Attach protocol handler}
- ENetAddMulti = 246; {Add a multicast address}
- ENetDelMulti = 245; {Delete a multicast address}
-
- _______________________________________________________________________________
-
- æKY Appletalk…Manager…Data…Types
- æC »Appletalk Manager Data Types AppleTalk Manager
- _______________________________________________________________________________
-
- TYPE ATQentry =
- RECORD
- qLink: ATQentryPtr; {next queue entry}
- qType: Integer; {reserved}
- CallAddr: ProcPtr; {pointer to your routine}
- END;
- ATQentryptr = ^ATQentry;
-
- ATPParamBlock =
- PACKED RECORD {extended parameter block for }
- { PSendRequest and PNSendRequest}
- qLink: QElemPtr; {next queue entry}
- qType: Integer; {queue type}
- ioTrap: Integer; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OsErr; {result code}
- userData: LongInt; {ATP user bytes}
- reqTID: Integer; {request transaction ID}
- ioRefNum: Integer; {driver reference number}
- csCode: Integer; {primary command code}
- atpSocket: Byte; {currBitMap or socket number}
- atpFlags: Byte; {control information - set bit 2 }
- { for extended parameter block}
- addrBlock: AddrBlock; {source socket address}
- reqLength: Integer; {request size in bytes}
- reqPointer: Ptr; {pointer to request data}
- bdsPointer: Ptr; {pointer to response Buffer }
- { Data Structure}
- numOfBuffs: Byte; {number of responses expected}
- timeOutVal: Byte; {timeout interval}
- numOfResps: Byte; {number of responses }
- { actually received}
- retryCount: Byte; {number of retries}
- intBuff: Integer; {used internally for NSendRequest}
- TRelTime: Byte {release timer setting}
-
- END;
-
- XPPParamBlock =
- PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: Integer; {queue type}
- ioTrap: Integer; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OsErr; {result code}
- cmdResult: LongInt; {command result}
- ioVRefNum: Integer; {volume reference number}
- ioRefNum: Integer; {driver reference number}
- csCode: Integer; {primary command code}
- CASE XPPPrmBlkType OF
- xCallParam
- xppSubCode: Integer; {secondary command code}
- xppTimeOut: Byte; {timeout period for .XPP}
- xppRetry: Byte; {retry count}
- filler1: Integer; {reserved}
- zipBuffPtr: Ptr; {returned zone names}
- zipNumZones: Integer; {number of zones returned}
- zipLastFlag: Byte; {nonzero when all zone }
- { names have been returned}
- filler2 Byte; {reserved}
- zipInfoField: packed array[1..70] of Byte
- {reserved for use by .XPP}
- END;
- XPPParmBlkPtr = ^XPPParamBlock;
-
- TRCCB =
- PACKED RECORD
- ccbLink: TPCCB; {link to next CCB}
- refNum: Integer; {reference number}
- state: Integer; {state of the connection end}
- userFlags: Byte; {user flags for connection}
- localSocket: Byte; {local socket number}
- remoteAddress: AddrBlock; {remote end internet address}
- attnCode: Integer; {attention code received}
- attnSize: Integer; {size of attention data}
- attnPtr: Ptr; {pointer to attention data}
- reserved: PACKED ARRAY [1..220] OF Byte
- {reserved for use by ADSP}
- END;
-
- AddrBlock =
- PACKED RECORD
- aNet: Integer; {network number}
- aNode: Byte; {node ID}
- aSocket: Byte; {socket number}
- END;
-
- DSPParamBlock =
- PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: Integer; {queue type}
- ioTrap: Integer; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OsErr; {result code}
- ioNamePtr: StringPtr; {reserved}
- ioVRefNum: Integer; {reserved}
- ioCRefNum: Integer; {driver reference number}
- csCode: Integer; {primary command code}
- qStatus: LongInt; {reserved for ADSP}
- ccbRefNum: Integer; {CCB reference number}
-
- CASE Integer OF
- dspInit,
- dspCLInit:
- (
- ccbPtr: TPCCB; {pointer to CCB}
- userRoutine: ProcPtr; {pointer to user routine}
- sendQSize: Integer; {size of send queue}
- sendQueue: Ptr; {pointer to send queue}
- recvQSize: Integer; {size of receive queue}
- recvQueue: Ptr; {pointer to receive queue}
- attnPtr: Ptr; {pointer to attention- }
- { message buffer}
- localSocket: Byte; {local socket number}
- filler1: Byte; {filler for proper alignment}
- );
-
- dspOpen,
- dspCLListen,
- dspCLDeny:
- (
- localCID: Integer; {local connection ID}
- remoteCID: Integer; {remote connection ID}
- remoteAddress: AddrBlock; {remote internet address}
- filterAddress: AddrBlock; {address filter}
- sendSeq: LongInt; {send sequence number}
- sendWindow: Integer; {size of remote buffer}
- recvSeq: LongInt; {receive sequence number}
- attnSendSeq: LongInt; {attention send seq number}
- attnRecvSeq: LongInt; {attention receive seq num}
- ocMode: Byte; {connection opening mode}
- ocInterval: Byte; {interval bet open requests}
- ocMaximum: Byte; {retries of open conn req}
- filler2: Byte; {filler for proper alignment}
- );
-
- dspClose,
- dspRemove:
- (
- abort: Byte; {abort send requests}
- filler3: Byte; {filler for proper alignment}
- );
-
- dspStatus:
- (
- statusCCB: TPCCB; {pointer to CCB}
- sendQPending: Integer; {bytes waiting in send queue}
- sendQFree: Integer; {available send-queue buffer}
- recvQPending: Integer; {bytes in receive queue}
- recvQFree: Integer; {avail receive-queue buffer}
- )
-
- dspRead,
- dspWrite:
- (
- reqCount: Integer; {requested number of bytes}
- actCount: Integer; {actual number of bytes}
- dataPtr: Ptr; {pointer to data buffer}
- eom: Byte; {1 if end of message}
- flush: Byte; {1 to send data now}
- )
-
- dspAttention:
- (
- attnCode: Integer; {client attention code}
- attnSize: Integer; {size of attention data}
- attnData: Ptr; {pointer to attention data}
- attnInterval: Byte; {reserved}
- filler4: Byte; {filler for proper alignment}
- )
-
- dspOptions:
- (
- sendBlocking: Integer; {send-blocking threshold}
- sendTimer: Byte; {reserved}
- rtmtTimer: Byte; {reserved}
- badSeqMax: Byte; {retransmit advice threshold}
- useCheckSum: Byte; {DDP checksum for packets}
- )
-
- dspNewCID:
- (
- newCID: Integer {new connection ID}
- )
- END;
-
- EParamBlock =
- PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: Integer; {queue type}
- ioTrap: Integer; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OsErr; {result code}
- ioNamePtr: StringPtr; {driver name}
- ioVRefNum: Integer; {volume reference number}
- ioRefNum: Integer; {driver reference number}
- csCode: Integer; {primary command code}
-
- CASE Integer OF
- ENetWrite,
- ENetAttachPH,
- ENetDetachPH,
- ENetRead,
- ENetRdCancel,
- ENetGetInfo,
- ENetSetGeneral:
- (
- eProtType: Integer; {Ethernet protocol type}
- ePointer: Ptr; {pointer; use depends on }
- { function}
- eBuffSize Integer; {buffer size}
- eDataSize Integer {number of bytes read}
- );
- ENetAddMulti,
- ENetDelMulti:
- (
- eMultiAddr: ARRAY [0..5] of Char {Multicast address}
- );
- END;
- EParamBlkPtr = ^EParamBlock;
- _______________________________________________________________________________
-
- æKY Appletalk…Manager…Routines…Summary
- æC »Appletalk Manager Routines Summary AppleTalk Manager
- _______________________________________________________________________________
-
- Getting Information About the .MPP Driver
-
- FUNCTION PGetAppleTalkInfo (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
-
- Adding and Removing AppleTalk Transition Queue Entries
-
- FUNCTION LAPAddATQ (theATQEntry: ATQEntryPtr): OSErr;
-
- FUNCTION LAPRmvATQ (theATQEntry: ATQEntryPtr): OSErr;
-
-
- Sending Messages to the AppleTalk Transition Queue
-
- FUNCTION PATalkClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
-
- Defining Your Own AppleTalk Transition
-
- PROCEDURE ATEvent (event: LongInt; infoPtr: Ptr);
-
- FUNCTION ATPreFlightEvent (event,cancel: LongInt; infoPtr: Ptr) : OSErr;
-
-
- Canceling All Calls to the ATPGetRequest Function
-
- FUNCTION ATPKillAllGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
-
-
- Obtaining Zone Information
-
- FUNCTION GetMyZone (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- FUNCTION GetLocalZones (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- FUNCTION GetZoneList (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
-
- Attaching and Detaching an Ethernet Protocol Handler
-
- FUNCTION EAttachPH (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- FUNCTION EDetachPH (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
-
- Writing and Reading Ethernet Packets
-
- FUNCTION EWrite (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- FUNCTION ERead (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- FUNCTION ERdCancel (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- FUNCTION EGetInfo (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- FUNCTION ESetGeneral (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
-
- Adding and Removing Ethernet Multicast Addresses
-
- FUNCTION EAddMulti (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
-
- FUNCTION EDelMulti (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
- _______________________________________________________________________________
-
- æKY Appletalk…Manager…Global…Variable
- æC »Appletalk Manager Global Variable AppleTalk Manager
- _______________________________________________________________________________
-
- LapMgrPtr The start of the LAP Manager
-
- _______________________________________________________________________________
-
- æKY Appletalk…Manager…Result…Codes
- æC »Appletalk Manager Result Codes AppleTalk Manager
- _______________________________________________________________________________
-
- noErr 0 no error
- qErr –1 Queue element not found
- closeErr –24 permission to close .MPP driver
- was denied
- paramErr –50 Version number is too high
- ddpSktErr –91 error opening socket
- eMultiErr –91 invalid address, address not found,
- or table is full
- eLenErr –92 packet too large or first entry of
- the write-data
- structure did not
- contain the full
- 14-byte header
- noBridgeErr –93 no router is available
- LAPProtErr –94 protocol handler is already attached,
- node’s protocol
- table is full, no
- protocol handler is
- attached, or
- protocol handler
- pointer was not 0
- excessCollsns –95 hardware error
- memFullErr –108 Insufficient memory in heap
- reqFailed –1096 request to contact router failed;
- retry count exceeded
- cbNotFound –1102 control block not found, no pending
- asynchronous
- calls, or ERead not
- active
- reqAborted –1105 ERdCancel or EDetachPH function
- called
- errOpenDenied –1273 open request denied by recipient
- errDSPQueueSize –1274 send or receive queue is too small
- errFwdReset –1275 read terminated by forward reset
- errAttention –1276 attention message too long
- errOpening –1277 attempt to open connection failed
- errState –1278 bad connection state for this
- operation
- errAborted –1279 request aborted by dspRemove or
- dspClose routine
- errRefNum –1280 bad connection reference number
- buf2SmallErr –3101 packet too large for buffer; partial
- data returned
- _______________________________________________________________________________
-
- æKY Appletalk…Manager…Assembly-language…Information
- æC »Appletalk Manager Assembly-language Information AppleTalk Manager
- _______________________________________________________________________________
-
- Constants
-
- ;ADSP queue element equates & size
- csQStatus .EQU CSParam ;adsp internal use
- csCCBRef .EQU csQStatus+4 ;refnum of ccb
-
-
- AppleTalk Transition Queue Entry Data Structure
-
- AeQQLink long next queue entry
- AeQQType word reserved
- AeQCallAddr long pointer to your routine
-
-
- ADSP Connection Control Block Data Structure
-
- ccbLink long link to next CCB
- refNum word reference number
- state word state of the connection end
- userFlags byte user flags for connection
- localSocket byte local socket number
- remoteAddress long internet address of remote end
- attnCode word attention code received
- attnSize word size of received attention data
- attnPtr long pointer to received attention data
- reserved 220 bytes reserved
-
-
- XPP Parameter Block xCallParam Variant
-
- ¨ 16 ioResult word result code
- Æ 26 csCode word routine
- selector; always xCall
- Æ 28 xppSubCode word routine selector
- subcode
- Æ 30 xppTimeOut byte retry interval
- in seconds
- Æ 31 xppRetry byte retry
- count
- Æ 34 zipBuffPtr long pointer to
- data buffer
- ¨ 38 zipNumZones word number of names
- returned
- ¨ 40 zipLastFlag byte nonzero if
- no more names
- Æ 42 zipInfoField 70 bytes for use by
- ZIP; first word set to 0
-
-
- Parameter Block for dspInit and dspCLInit
-
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word dspInit or dspCLInit
- ¨ 32 ccbRefNum word reference number of CCB
- Æ 34 ccbPtr long pointer to CCB
- Æ 38 userRoutine long pointer to routine to call
- on
-
- events
- Æ 42 sendQSize word size in bytes of the send
- queue
- Æ 44 sendQueue long pointer to send queue
- Æ 48 recvQSize word size in bytes of the
- receive queue
- Æ 50 recvQueue long pointer to receive queue
- Æ 54 attnPtr long pointer to buffer
- for incoming
-
-
-
- ´ 58 localSocket byte DDP socket number for
- this
-
- end
-
-
- Parameter Block for dspOptions
-
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word always dspOptions
- Æ 32 ccbRefNum word reference number of CCB
- Æ 34 sendBlocking word send-blocking threshold
- Æ 38 badSeqMax byte threshold to send
- retransmit advice
- Æ 39 useCheckSum byte use DDP checksum?
-
-
- Parameter Block for dspOpen, dspCLListen, and dspCLDeny
-
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word dspOpen,
- dspCLListen, or
-
-
- Æ 32 ccbRefNum word reference number of CCB
- ¨ 34 localCID word ID of this connection
- end
- ´ 36 remoteCID word ID of remote connection
- end
- ´ 38 remoteAddress long remote internet address
- Æ 42 filterAddress long filter for open
- connection requests
- ´ 46 sendSeq long initial send
- sequence number
- ´ 50 sendWindow word initial size of remote
- receive queue
- Æ 52 recvSeq long initial receive
- sequence number
- ´ 56 attnSendSeq long attention send sequence
- number
- Æ 60 attnRecvSeq long attention receive
- sequence number
- Æ 64 ocMode byte connection-opening
- mode
- Æ 65 ocInterval byte interval between
- open requests
- Æ 66 ocMaximum byte retries of open-connection
- request
-
-
- Parameter Block for dspNewCID
-
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word always dspNewCID
- Æ 32 ccbRefNum word reference number of CCB
- ¨ 34 newCID word ID of new connection
-
-
- Parameter Block for dspClose, dspRemove, and dspCLRemove, and dspCLRemove
-
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word dspClose, dspRemove,
- or
-
-
- Æ 32 ccbRefNum word reference number of CCB
- Æ 34 abort byte abort send
- requests or connection
-
- if
- not
- 0
-
-
- Parameter Block for dspStatus
-
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference
- number
- Æ 26 csCode word always
- dspStatus
- Æ 32 ccbRefNum word reference number of
- CCB
- ¨ 34 statusCCB pointer pointer to CCB
- ¨ 38 sendQPending word bytes waiting to be
- sent or
-
-
- ¨ 40 sendQFree word available send
- queue in bytes
- ¨ 42 recvQPending word bytes waiting to be
- read from queue
- ¨ 44 recvQFree word available receive
- queue in bytes
-
-
- Parameter Block for dspRead and dspWrite
-
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word dspRead or dspWrite
- Æ 32 ccbRefNum word reference number of CCB
- Æ 34 reqCount word requested number of
- bytes
- ¨ 36 actCount word actual number of bytes
- read or
-
-
- Æ 38 dataPtr pointer pointer to data
- buffer
- ¨ 42 eom byte 1 if
- end-of-message; 0 otherwise
- Æ 43 flush byte 1 to send data
- now; 0 otherwise
-
-
- Parameter Block for dspAttention and dspReset
-
- ¨ 16 ioResult word result code
- Æ 24 ioCRefNum word driver reference number
- Æ 26 csCode word dspAttention or
- dspReset
- Æ 32 ccbRefNum word reference number of CCB
- Æ 34 attnCode word client attention
- code
- Æ 36 attnSize word size of attention
- data in bytes
- Æ 38 attnData pointer pointer to
- attention data
-
-
- .ENET Driver Parameter Block
-
- 16 ¨ ioResult word result code
- 26 Æ csCode word routine selector
- 28 Æ eMultiAddr 6 bytes multicast address
- 28 Æ eProtType word Ethernet protocol
- type
- 30 Æ ePointer long pointer
- 34 Æ eBuffSize word size of buffer
- 36 ¨ eDataSize word number of bytes read
- _______________________________________________________________________________
-
-
- æKY About…The…AppleTalkManager…Chapter
- æC »ABOUT THIS CHAPTER AppleTalkManager
- _______________________________________________________________________________
-
- The AppleTalk Manager is an interface to a pair of RAM device drivers that allow
- Macintosh programs to send and receive information via an AppleTalk network. This
- chapter describes the AppleTalk Manager in detail.
-
- The AppleTalk Manager has been enhanced through the implementation of new protocols
- and an increase in the functionality of the existing interface.
-
- Reader’s guide: The AppleTalk Manager provides services that allow Macintosh
- programs to interact with clients in devices connected to an
- AppleTalk network. Hence you need the information in this
- chapter only if your application uses AppleTalk.
-
- The following is a brief summary of the changes that have been made to the AppleTalk
- Manager interface.
-
- • New parameter block–style Pascal calls have been added for the entire
- AppleTalk Manager. These new calls give the application programmer
- better control of AppleTalk operation within an application.
- • At open time, the .MPP driver can be told to pick a node number in
- the server range. This is a more time consuming but more thorough
- operation than is selecting a node number in the workstation range,
- and it is required for devices acting as servers.
- • Multiple concurrent NBP requests are now supported (just as multiple
- concurrent ATP requests have been supported). The KillNBP command
- has been implemented to abort an outstanding NBP request.
- • ATP requests can now be sent through client-specified sockets, instead
- of having ATP pick the socket itself.
- • The ability to send packets to one’s own node is supported (although
- this functionality is, in the default case, disabled).
- • Two new ATP abort calls have been added: KillSendReq and KillGetReq.
- KillSendReq is functionally equivalent to RelTCB, although its
- arguments are different. KillGetReq is a new call for aborting
- outstanding GetRequests.
- • Additional machine-dependent resources have been added to support,
- for example, more dynamic sockets and more concurrent ATP requests.
- • A new protocol called the Echo Protocol (EP) is supported.
- • A new driver, .XPP, has been added. The .XPP driver implements the
- workstation side of the AppleTalk Session Protocol (ASP) and a small
- portion of the AppleTalk Filing Protocol.
-
- To determine if your application is running on a machine that supports these enhanced
- features, check the version number of the .MPP driver (at offset DCtlQueue+1 in the
- Device Control Entry). A version number of 48 (NCVersion) or greater indicates the
- presence of the new drivers.
-
- You should already be familiar with:
-
- • events, as discussed in the Toolbox Event Manager chapter
- • interrupts and the use of devices and device drivers, as described in
- the Device Manager chapter, if you want to write your own assembly-
- language additions to the AppleTalk Manager
- • the Inside AppleTalk manual, if you want to understand AppleTalk
- protocols in detail
-
- _______________________________________________________________________________
-
-
- æKY AppleTalk…Protocols
- æC »APPLETALK PROTOCOLS AppleTalkManager
- _______________________________________________________________________________
-
- The AppleTalk Manager provides a variety of services that allow Macintosh programs to
- interact with programs in devices connected to an AppleTalk network. This interaction,
- achieved through the exchange of variable-length blocks of data (known as packets)
- over AppleTalk, follows well-defined sets of rules known as protocols.
-
- Although most programmers using AppleTalk needn’t understand the details of these
- protocols, they should understand the information in this section—what the services
- provided by the different protocols are, and how the protocols are interrelated.
- Detailed information about AppleTalk protocols is available in Inside AppleTalk.
-
- The AppleTalk system architecture consists of a number of protocols arranged in
- layers. Each protocol in a specific layer provides services to higher-level layers
- (known as the protocol’s clients) by building on the services provided by lower-level
- layers. A Macintosh program can use services provided by any of the layers in order
- to construct more sophisticated or more specialized services. Figure 1 shows the
- AppleTalk Protocols and their corresponding network layers.
-
- The AppleTalk Manager contains the following protocols:
-
- • AppleTalk Link Access Protocol
- • Datagram Delivery Protocol
- • Routing Table Maintenance Protocol
- • Name-Binding Protocol
- • AppleTalk Transaction Protocol
-
- The following protocols have been added to the AppleTalk Manager:
-
- • Echo Protocol
- • AppleTalk Session Protocol (workstation side)
- • AppleTalk Filing Protocol (small portion of the workstation side)
-
- In Figure 1, the lines indicate the interaction between the protocols. Notice that
- like the Routing Table Maintenance Protocol, the Echo Protocol is not directly accessible
- to Macintosh programs.
-
- The details of these protocols are provided in Inside AppleTalk.
-
- •••Refer to Figure 1.•••
-
- Figure 1–AppleTalk Protocols and OSI Network Layers
-
- Figure 2 illustrates the Macintosh AppleTalk Drivers and the layered structure of the
- protocols which are accessible through each driver. Note that the Routing Table
- Maintenance Protocol isn’t directly accessible to Macintosh Programs.
-
- •••Refer to Figure 2.•••
-
- Figure 2–Macintosh AppleTalk Drivers
-
- The AppleTalk Link Access Protocol (ALAP) provides the lowest-level services of the
- AppleTalk system. Its main function is to control access to the AppleTalk network
- among various competing devices. Each device connected to an AppleTalk network, known
- as a node, is assigned an eight-bit node ID number that identifies the node. ALAP
- ensures that each node on an AppleTalk network has a unique node ID, assigned dynamically
- when the node is started up.
-
- ALAP provides its clients with node-to-node delivery of data frames on a single
- AppleTalk network. An ALAP frame is a variable-length packet of data preceded and
- followed by control information referred to as the ALAP frame header and frame trailer,
- respectively. The ALAP frame header includes the node IDs of the frame’s destination
- and source nodes. The AppleTalk hardware uses the destination node ID to deliver the
- frame. The frame’s source node ID allows a program in the receiving node to determine
- the identity of the source. A sending node can ask ALAP to send a frame to all nodes
- on the AppleTalk network; this broadcast service is obtained by specifying a destination
- node ID of 255.
-
- ALAP can have multiple clients in a single node. When a frame arrives at a node, ALAP
- determines which client it should be delivered to by reading the frame’s ALAP protocol
- type. The ALAP protocol type is an eight-bit quantity, contained in the frame’s
- header, that identifies the ALAP client to whom the frame will be sent. ALAP calls
- the client’s protocol handler, which is a software process in the node that reads in
- and then services the frames. The protocol handlers for a node are listed in a protocol
- handler table.
-
- An ALAP frame trailer contains a 16-bit frame check sequence generated by the AppleTalk
- hardware. The receiving node uses the frame check sequence to detect transmission
- errors, and discards frames with errors. In effect, a frame with an error is “lost”
- in the AppleTalk network, because ALAP doesn’t attempt to recover from errors by
- requesting the sending node to retransmit such frames. Thus ALAP is said to make a
- “best effort” to deliver frames, without any guarantee of delivery.
-
- An ALAP frame can contain up to 600 bytes of client data. The first two bytes must be
- an integer equal to the length of the client data (including the length bytes themselves).
-
- Datagram Delivery Protocol (DDP) provides the next-higher level protocol in the
- AppleTalk architecture, managing socket-to-socket delivery of datagrams over AppleTalk
- internets. DDP is an ALAP client, and uses the node-to-node delivery service provided
- by ALAP to send and receive datagrams. Datagrams are packets of data transmitted by
- DDP. A DDP datagram can contain up to 586 bytes of client data. Sockets are logical
- entities within the nodes of a network; each socket within a given node has a unique
- eight-bit socket number.
-
- On a single AppleTalk network, a socket is uniquely identified by its AppleTalk
- address—its socket number together with its node ID. To identify a socket in the
- scope of an AppleTalk internet, the socket’s AppleTalk address and network number are
- needed. Internets are formed by interconnecting AppleTalk networks via intelligent
- nodes called bridges. A network number is a 16-bit number that uniquely identifies a
- network in an internet. A socket’s AppleTalk address together with its network number
- provide an internet-wide unique socket identifier called an internet address.
-
- Sockets are owned by socket clients, which typically are software processes in the
- node. Socket clients include code called the socket listener, which receives and
- services datagrams addressed to that socket. Socket clients must open a socket before
- datagrams can be sent or received through it. Each node contains a socket table that
- lists the listener for each open socket.
-
- A datagram is sent from its source socket through a series of AppleTalk networks,
- being passed on from bridge to bridge, until it reaches its destination network. The
- ALAP in the destination network then delivers the datagram to the node containing the
- destination socket. Within that node the datagram is received by ALAP calling the DDP
- protocol handler, and by the DDP protocol handler in turn calling the destination
- socket listener, which for most applications will be a higher-level protocol such as
- the AppleTalk Transaction Protocol.
-
- Bridges on AppleTalk internets use the Routing Table Maintenance Protocol (RTMP) to
- maintain routing tables for routing datagrams through the internet. In addition,
- nonbridge nodes use RTMP to determine the number of the network to which they’re
- connected and the node ID of one bridge on their network. The RTMP code in nonbridge
- nodes contains only a subset of RTMP (the RTMP stub), and is a DDP client owning
- socket number 1 (the RTMP socket).
-
- Socket clients are also known as network-visible entities, because they’re the primary
- accessible entities on an internet. Network-visible entities can choose to identify
- themselves by an entity name, an identifier of the form
-
- object:type@zone
-
- Each of the three fields of this name is an alphanumeric string of up to 32 characters.
- The object and type fields are arbitrary identifiers assigned by a socket client, to
- provide itself with a name and type descriptor (for example, abs:Mailbox). The zone
- field identifies the zone in which the socket client is located; a zone is an arbitrary
- subset of AppleTalk networks in an internet. A socket client can identify itself by
- as many different names as it chooses. These aliases are all treated as independent
- identifiers for the same socket client.
-
- The Name-Binding Protocol (NBP) maintains a names table in each node that contains
- the name and internet address of each entity in that node. These name-address pairs
- are called NBP tuples. The collection of names tables in an internet is known as the
- names directory.
-
- NBP allows its clients to add or delete their name-address tuples from the
- node’s names table. It also allows its clients to obtain the internet addresses of
- entities from their names. This latter operation, known as name lookup (in the names
- directory), requires that NBP install itself as a DDP client and broadcast special
- name-lookup packets to the nodes in a specified zone. These datagrams are sent by NBP
- to the names information socket—socket number 2 in every node using NBP.
-
- NBP clients can use special meta-characters in place of one or more of the three
- fields of the name of an entity it wishes to look up. The character “=” in the object
- or type field signifies “all possible values”. The zone field can be replaced by “*”,
- which signifies “this zone”—the zone in which the NBP client’s node is located. For
- example, an NBP client performing a lookup with the name
-
- =:Mailbox@*
-
- will obtain in return the entity names and internet addresses of all mailboxes in the
- client’s zone (excluding the client’s own names and addresses). The client can specify
- whether one or all of the matching names should be returned.
-
- NBP clients specify how thorough a name lookup should be by providing NBP with the
- number of times (retry count) that NBP should broadcast the lookup packets and the
- time interval (retry interval) between these retries.
-
- As noted above, ALAP and DDP provide “best effort” delivery services with no recovery
- mechanism when packets are lost or discarded because of errors. Although for many
- situations such a service suffices, the AppleTalk Transaction Protocol (ATP) provides
- a reliable loss-free transport service. ATP uses transactions, consisting of a transaction
- request and a transaction response, to deliver data reliably. Each transaction is
- assigned a 16-bit transaction ID number to distinguish it from other transactions. A
- transaction request is retransmitted by ATP until a complete response has been received,
- thus allowing for recovery from packet-loss situations. The retry interval and retry
- count are specified by the ATP client sending the request.
-
- Although transaction requests must be contained in a single datagram, transaction
- responses can consist of as many as eight datagrams. Each datagram in a response is
- assigned a sequence number from 0 to 7, to indicate its ordering within the response.
-
- ATP is a DDP client, and uses the services provided by DDP to transmit requests and
- responses. ATP supports both at-least-once and exactly-once transactions. Four of the
- bytes in an ATP header, called the user bytes, are provided for use by ATP’s clients—they’re
- ignored by ATP.
-
- ATP’s transaction model and means of recovering from datagram loss are covered in
- detail below.
-
- The Echo Protocol (EP) provides an echoing service through static socket number 4
- known as the echoer socket. The echoer listens for packets received through this
- socket. Any correctly formed packet sent to the echoer socket on a node will be
- echoed back to its sender.
-
- This simple protocol can be used for two important purposes:
-
- • EP can be used by any Datagram Delivery Protocol (DDP) client to
- determine if a particular node (known to have an echoer) is accessible
- over an internet.
- • EP is useful in determining the average time it takes for a packet to
- travel to a remote node and back. This is very helpful in developing
- client-dependent heuristics for estimating the timeouts to be specified
- by clients of ATP, ASP, and other protocols.
-
- Programs cannot access EP directly via the AppleTalk Manager. The EP implementation
- exists solely to respond to EP requests sent by other nodes. EP is a DDP client
- residing on statically-assigned socket 4, the echoing socket. Clients wishing to
- send EP requests (and receive EP responses) should use the Datagram Delivery Protocol
- (DDP) to send the appropriate packet. For more information about the EP packet
- format, see Inside AppleTalk.
-
- The AppleTalk Session Protocol (ASP) provides for the setting up, maintaining and
- closing down of a session. A session is a logical relationship between two network
- entities, a workstation and a server. The workstation tells the server what to do,
- and the server responds with the appropriate actions. ASP makes sure that the session
- dialog is maintained in the correct sequence and that both ends of the conversation
- are properly participating.
-
- ASP will generally be used between two communicating network entities where one is
- providing a service to the other (for example, a server is providing a service to a
- workstation) and the service provided is state-dependent. That is, the response to a
- particular request from an entity is dependent upon other previous requests from that
- entity. For example, a request to read bytes from a file is dependent upon a previous
- request to open that file in the first place. However, a request to return the time
- of day is independent of all such previous requests.
-
- When the service provided is state-dependent, requests must be delivered to the
- server in the same order as generated by the workstation. ASP guarantees requests
- are delivered to the server in the order in which they are issued, and that duplicate
- requests are never delivered (another requirement of state-dependent service).
-
- ASP is an asymmetric protocol, providing one set of services to the workstation and a
- different set of services to the server.
-
- ASP workstation clients initiate (open) sessions, send requests (commands) on that
- session, and close sessions down. ASP server clients receive and respond
- (through command replies) to these requests. ASP guarantees that these requests are
- delivered in the same order as they are made, and without duplication. ASP is also
- responsible for closing down the session if one end fails or becomes unreachable, and
- will inform its client (either server or workstation) of the action.
-
- ASP also provides various additional services, such as allowing a workstation to
- obtain server status information without opening a session to a server, writing
- blocks of data from the workstation to the server end of the session, and providing
- the ability for a server to send an attention message to the workstation.
-
- ASP assumes that the workstation client has a mechanism for looking up the network
- address of the server with which it wants to set up a session.
- (Generally this is done using the AppleTalk Name Binding Protocol.)
-
- Both ends of the session periodically check to see that the other end of the session
- is still responsive. If one end fails or becomes unreachable the other end closes
- the session.
-
- ASP is a client of ATP and calls ATP for transport services.
-
- ASP does not
-
- • ensure that consecutive commands complete in the order in which they
- were sent (and delivered) to the server
- • understand or interpret the syntax or the semantics of the commands
- sent to the server by the workstation
- • allow the server to send commands to the workstation (The server
- is allowed to alert the workstation through the server’s attention
- mechanism only.)
-
- Note: The .XPP driver does implement the workstation side of the
- AppleTalk Filing Protocol login command.
-
- The AppleTalk Filing Protocol (AFP) allows a workstation on an AppleTalk network to
- access files on an AFP file server. AFP specifies a remote filing system that provides
- user authentication and an access control mechanism that supports volume and folder-level
- access rights. For details of AFP, refer to Inside AppleTalk.
-
- _______________________________________________________________________________
-
-
- æKY AppleTalk…Transaction…Protocol
- æC »APPLETALK TRANSACTION PROTOCOL AppleTalkManager
- _______________________________________________________________________________
-
- This section covers ATP in greater depth, providing more detail about three of its
- fundamental concepts: transactions, buffer allocation, and recovery of lost datagrams.
-
- _______________________________________________________________________________
-
- »Transactions
-
- A transaction is a interaction between two ATP clients, known as the requester and
- the responder. The requester calls the .ATP driver in its node to send a transaction
- request (TReq) to the responder, and then awaits a response. The TReq is received by
- the .ATP driver in the responder’s node and is delivered to the responder. The responder
- then calls its .ATP driver to send back a transaction response (TResp), which is
- received by the requester’s .ATP driver and delivered to the requester. Figure 3
- illustrates this process.
-
- •••Refer to Figure 3.•••
-
- Figure 3–Transaction Process
-
- Simple examples of transactions are:
-
- • read a counter, reset it and send back the value read
- • read six sectors of a disk and send back the data read
- • write the data sent in the TReq to a printer
-
- A basic assumption of the transaction model is that the amount of ATP data sent in
- the TReq specifying the operation to be performed is small enough to fit in a single
- datagram. A TResp, on the other hand, may span several datagrams, as in the second
- example. Thus, a TReq is a single datagram, while a TResp consists of up to eight
- datagrams, each of which is assigned a sequence number from 0 to 7 to indicate its
- position in the response.
-
- The requester must, before calling for a TReq to be sent, set aside enough buffer
- space to receive the datagram(s) of the TResp. The number of buffers allocated (in
- other words, the maximum number of datagrams that the responder can send) is indicated
- in the TReq by an eight-bit bit map. The bits of this bit map are numbered 0 to 7
- (the least significant bit being number 0); each bit corresponds to the response
- datagram with the respective sequence number.
-
- _______________________________________________________________________________
-
- »Datagram Loss Recovery
-
- The way that ATP recovers from datagram loss situations is best explained by an
- example; see Figure 4. Assume that the requester wants to read six sectors of 512
- bytes each from the responder’s disk. The requester puts aside six 512-byte buffers
- (which may or may not be contiguous) for the response datagrams, and calls ATP to
- send a TReq. In this TReq the bit map is set to binary 00111111 or decimal 63. The
- TReq carries a 16-bit transaction ID, generated by the requester’s .ATP driver before
- sending it. (This example assumes that the requester and responder have already
- agreed that each buffer can hold 512
- bytes.) The TReq is delivered to the responder, which reads the six disk sectors and
- sends them back, through ATP, in TResp datagrams bearing sequence numbers 0 through
- 5. Each TResp datagram also carries exactly the same transaction ID as the TReq to
- which they’re responding.
-
- There are several ways that datagrams may be lost in this case. The original TReq
- could be lost for one of many reasons. The responding node might be too busy to
- receive the TReq or might be out of buffers for receiving it, there could be an
- undetected collision on the network, a bit error in the transmission line, and so on.
- To recover from such errors, the requester’s .ATP driver maintains an ATP retry timer
- for each transaction sent. If this timer expires and the complete TResp has not been
- received, the TReq is retransmitted and the retry timer is restarted.
-
- A second error situation occurs when one or more of the TResp datagrams isn’t received
- correctly by the requester’s .ATP driver (datagram 1 in Figure 4). Again, the retry
- timer will expire and the complete TResp will not have been received; this will
- result in a retransmission of the TReq. However, to avoid unnecessary retransmission
- of the TResp datagrams already properly received, the bit map of this retransmitted
- TReq is modified to reflect only those datagrams not yet received. Upon receiving
- this TReq, the responder retransmits only the missing response datagrams.
-
- Another possible failure is that the responder’s .ATP driver goes down or the responder
- becomes unreachable through the underlying network system. In this case, retransmission
- of the TReq could continue indefinitely. To avoid this situation, the requester
- provides a maximum retry count; if this count is exceeded, the requester’s .ATP
- driver returns an appropriate error message to the requester.
-
- •••Refer to Figure 4.•••
-
- Figure 4–Datagram Loss Recovery
-
- Note: There may be situations where, due to an anticipated delay, you’ll
- want a request to be retransmitted more than 255 times; specifying a
- retry count of 255 indicates “infinite retries” to ATP and will cause
- a message to be retransmitted until the request has either been
- serviced, or been cancelled through a specific call.
- _______________________________________________________________________________
-
- »THE APPLETALK MANAGER
- _______________________________________________________________________________
-
- Finally, in our example, what if the responder is able to provide only four disk
- sectors (having reached the end of the disk) instead of the six requested? To handle
- this situation, there’s an end-of-message (EOM) flag in each TResp datagram. In this
- case, the TResp datagram numbered 3 would come with this flag set. The reception of
- this datagram informs the requester’s .ATP driver that TResps numbered 4 and 5 will
- not be sent and should not be expected.
-
- When the transaction completes successfully (all expected TResp datagrams are received
- or TResp datagrams numbered 0 to n are received with datagram n’s EOM flag set), the
- requester is informed and can then use the data received in the TResp.
-
- ATP provides two classes of service: at-least-once (ALO) and exactly-once (XO). The
- TReq datagram contains an XO flag that’s set if XO service is required and cleared if
- ALO service is adequate. The main difference between the two is in the sequence of
- events that occurs when the TReq is received by the responder’s .ATP driver.
-
- In the case of ALO service, each time a TReq is received (with the XO flag cleared),
- it’s delivered to the responder by its .ATP driver; this is true even for retransmitted
- TReqs of the same transaction. Each time the TReq is delivered, the responder performs
- the requested operation and sends the necessary TResp datagrams. Thus, the requested
- operation is performed at least once, and perhaps several times, until the transaction
- is completed at the requester’s end.
-
- The at-least-once service is satisfactory in a variety of situations—for instance, if
- the requester wishes to read a clock or a counter being maintained at the responder’s
- end. However, in other circumstances, repeated execution of the requested operation
- is unacceptable. This is the case, for instance, if the requester is sending data to
- be printed at the responding end; exactly-once service is designed for such situations.
-
- The responder’s .ATP driver maintains a transactions list of recently received XO
- TReqs. Whenever a TReq is received with its XO flag set, the driver goes through this
- list to see if this is a retransmitted TReq. If it’s the first TReq of a transaction,
- it’s entered into the list and delivered to the responder. The responder executes the
- requested operation and calls its driver to send a TResp. Before sending it out, the
- .ATP driver saves the TResp in the list.
-
- When a retransmitted TReq for the same XO transaction is received, the responder’s
- .ATP driver will find a corresponding entry in the list. The retransmitted TReq is
- not delivered to the responder; instead, the driver automatically retransmits the
- response datagrams that were saved in the list. In this way, the responder never sees
- the retransmitted TReqs and the requested operation is performed only once.
-
- ATP must include a mechanism for eventually removing XO entries from the responding
- end’s transaction list; two provisions are made for this. When the requester’s .ATP
- driver has received all the TResp datagrams of a particular transaction, it sends a
- datagram known as a transaction release (TRel); this tells the responder’s .ATP
- driver to remove the transaction from the list. However, the TRel could be lost in
- the network (or the responding end may die, and so on), leaving the entry in the list
- forever. To account for this situation, the responder’s .ATP driver maintains a
- release timer for each transaction. If this timer expires and no activity has occurred
- for the transaction, its entry is removed from the transactions list.
-
- _______________________________________________________________________________
-
-
- æKY About…the…AppleTalk…Manager
- æC »ABOUT THE APPLETALK MANAGER AppleTalkManager
- _______________________________________________________________________________
-
- The AppleTalk Manager is divided into three parts (see Figure 5):
-
- • A lower-level driver called “.MPP” that contains code to implement ALAP,
- DDP, NBP, and the RTMP stub; this includes separate code resources loaded
- in when an NBP name is registered or looked up.
- • A higher-level driver called “.ATP” that implements ATP.
- • A Pascal interface to these two drivers, which is a set of Pascal data
- types and routines to aid Pascal programmers in calling the AppleTalk
- Manager.
-
- •••Refer to Figure 5.•••
-
- Figure 5–Calling the AppleTalk Manager
-
- The two drivers and the interface to them are not in ROM; your application must link
- to the appropriate object files.
-
- Pascal programmers make calls to the AppleTalk Manager’s Pascal interface, which in
- turn makes Device Manager Control calls to the two drivers. Assembly-language programmers
- make Device Manager Control calls directly to the drivers.
-
- Note: Pascal programmers can, of course, make PBControl calls directly
- if they wish.
-
- The AppleTalk Manager provides ALAP routines that allow a program to:
-
- • send a frame to another node
- • receive a frame from another node
- • add a protocol handler to the protocol handler table
- • remove a protocol handler from the protocol handler table
-
- Each node may have up to four protocol handlers in its protocol handler table, two of
- which are currently used by DDP.
-
- By calling DDP, socket clients can:
-
- • send a datagram via a socket
- • receive a datagram via a socket
- • open a socket and add a socket listener to the socket table
- • close a socket and remove a socket listener from the socket table
-
- Each node may have up to 12 open sockets in its socket table.
-
- Programs cannot access RTMP directly via the AppleTalk Manager; RTMP exists solely
- for the purpose of providing DDP with routing information.
-
- The NBP code allows a socket client to:
-
- • register the name and socket number of an entity in the node’s names table
- • determine the address (and confirm the existence) of an entity
- • delete the name of an entity from the node’s names table
-
- The AppleTalk Manager’s .ATP driver allows a socket client to do the following:
-
- • open a responding socket to receive requests
- • send a request to another socket and get back a response
- • receive a request via a responding socket
- • send a response via a responding socket
- • close a responding socket
-
- Note: Although the AppleTalk Manager provides four different protocols
- for your use, you’re not bound to use all of them. In fact, most
- programmers will use only the NBP and ATP protocols.
-
- AppleTalk communicates via channel B of the Serial Communications Controller
- (SCC). When the Macintosh is started up with a disk containing the AppleTalk code,
- the status of serial port B is checked. If port B isn’t being used by another device
- driver, and is available for use by AppleTalk, the .MPP driver is loaded into the
- system heap. On a Macintosh 128K, only the MPP code is loaded at system startup; the
- .ATP driver and NBP code are read into the application heap when the appropriate
- commands are issued. On a Macintosh 512K or XL, all AppleTalk code is loaded into the
- system heap at system startup.
-
- After loading the AppleTalk code, the .MPP driver installs its own interrupt handlers,
- installs a task into the vertical retrace queue, and prepares the SCC for use. It
- then chooses a node ID for the Macintosh and confirms that the node ID isn’t already
- being used by another node on the network.
-
- Warning: For this reason it’s imperative that the Macintosh be connected
- to the AppleTalk network through serial port B (the printer port)
- before being switched on.
-
- The AppleTalk Manager also provides Pascal routines for opening and closing the .MPP
- and .ATP drivers. The open calls allow a program to load AppleTalk code at times
- other than system startup. The close calls allow a program to remove the AppleTalk
- code from the Macintosh; the use of close calls is highly discouraged, since other
- co-resident programs are then “disconnected” from AppleTalk. Both sets of calls are
- described in detail under “Calling the AppleTalk Manager from Pascal”.
-
- Warning: If, at system startup, serial port B isn’t available for use by
- AppleTalk, the .MPP driver won’t open. However, a driver doesn’t
- return an error message when it fails to open. Pascal programmers
- must ensure the proper opening of AppleTalk by calling one of the
- two routines for opening the AppleTalk drivers (either MPPOpen or
- ATPLoad). If AppleTalk was successfully loaded at system startup,
- these calls will have no effect; otherwise they’ll check the
- availability of port B, attempt to load the AppleTalk code, and
- return an appropriate result code.
-
- Assembly-language note: Assembly-language programmers can use the Pascal
- routines for opening AppleTalk. They can also check
- the availability of port B themselves and then decide
- whether to open MPP or ATP. Detailed information on
- how to do this is provided in the section “Calling
- the AppleTalk Manager from Assembly Language”.
-
- The two AppleTalk device drivers, named .MPP and .ATP, are included in the 128K ROM.
- The AppleTalk Manager, however (the interface to the drivers), is not in ROM; your
- application must link to the appropriate object files.
-
- On the Macintosh Plus, you need only open the .MPP driver; this will also load the
- .ATP driver and NBP code automatically. Since, in the 128K ROM, device drivers return
- errors, it’s no longer necessary to check whether port B is free and configured for
- AppleTalk. If port B isn’t available, the .MPP driver won’t open and the result code
- portInUse or portNotCf will be returned.
-
- Assembly-language note: When called from assembly language, the Datagram
- Delivery Protocol (DDP) allows 14 (instead of 12)
- open sockets.
-
- The changes to the AppleTalk manager increase functionality and resources. Two interfaces
- for the AppleTalk Manager calls are discussed: the new or preferred interface and the
- alternate interface. Picking a node address in the server range, sending packets to
- one’s own node, multiple concurrent NBP requests, sending ATP requests through a
- specified socket and two new ATP calls are also discussed in this section. These
- calls can only be made with the preferred interface.
-
- _______________________________________________________________________________
-
-
- æKY Calling…the…AppleTalk…Manager…from…Pascal
- æC »CALLING THE APPLETALK MANAGER FROM PASCAL AppleTalkManager
- _______________________________________________________________________________
-
- This section discusses how to use the AppleTalk Manager from Pascal. Equivalent
- assembly-language information is given in the “Calling the AppleTalk Manager from
- Assembly Language” section.
-
- You can execute many AppleTalk Manager routines either synchronously (meaning that
- the application can’t continue until the routine is completed) or asynchronously
- (meaning that the application is free to perform other tasks while the routine is
- being executed).
-
- When an application calls an AppleTalk Manager routine asynchronously, an I/O request
- is placed in the appropriate driver’s I/O queue, and control returns to the calling
- program—possibly even before the actual I/O is completed. Requests are taken from the
- queue one at a time, and processed; meanwhile, the calling program is free to work on
- other things.
-
- The routines that can be executed asynchronously contain a Boolean parameter called
- async. If async is TRUE, the call is executed asynchronously; otherwise the call is
- executed synchronously. Every time an asynchronous routine call is completed, the
- AppleTalk Manager posts a network event. The message field of the event record will
- contain a handle to the parameter block that was used to make that call.
-
- Most AppleTalk Manager routines return an integer result code of type OSErr. Each
- routine description lists all of the applicable result codes generated by the AppleTalk
- Manager, along with a short description of what the result code means. Lengthier
- explanations of all the result codes can be found in the summary at the end of the
- chapter. Result codes from other parts of the Operating System may also be returned.
- (See Appendix A for a list of all result codes.)
-
- Many Pascal calls to the AppleTalk Manager require information passed in a parameter
- block of type ABusRecord. The exact content of an ABusRecord depends on the protocol
- being called:
-
- TYPE ABProtoType = (lapProto,ddpProto,nbpProto,atpProto);
- ABusRecord = RECORD
- abOpcode: ABCallType; {type of call}
- abResult: INTEGER; {result code}
- abUserReference: LONGINT; {for your use}
- CASE ABProtoType OF
- lapProto:
- . . . {ALAP parameters}
- ddpProto:
- . . . {DDP parameters}
- nbpProto:
- . . . {NBP parameters}
- atpProto:
- . . . {ATP parameters}
- END;
- END;
-
- ABRecPtr = ^ABusRecord;
- ABRecHandle = ^ABRecPtr;
-
- The value of the abOpcode field is inserted by the AppleTalk Manager when the call is
- made, and is always a member of the following set:
-
- TYPE ABCallType = (tLAPRead,tLAPWrite,tDDPRead,tDDPWrite,tNBPLookup,
- tNBPConfirm,tNBPRegister,tATPSndRequest,
- tATPGetRequest,tATPSdRsp,tATPAddRsp,tATPRequest,
- tATPRespond);
-
- The abUserReference field is available for use by the calling program in any way it
- wants. This field isn’t used by the AppleTalk Manager routines or drivers.
-
- The size of an ABusRecord data structure in bytes is given by one of the following
- constants:
-
- CONST lapSize = 20;
- ddpSize = 26;
- nbpSize = 26;
- atpSize = 56;
-
- Variables of type ABusRecord must be allocated in the heap with Memory Manager NewHandle
- calls. For example:
-
- myABRecord := ABRecHandle(NewHandle(ddpSize))
-
- Warning: These Memory Manager calls can’t be made inside interrupts.
-
- Routines that are executed asynchronously return control to the calling program with
- the result code noErr as soon as the call is placed in the driver’s I/O queue. This
- isn’t an indication of successful call completion; it simply indicates that the call
- was successfully queued to the appropriate driver. To determine when the call is
- actually completed, you can either check for a network event or poll the abResult
- field of the call’s ABusRecord. The abResult field, set to 1 when the call is made,
- receives the actual result code upon completion of the call.
-
- Warning: A data structure of type ABusRecord is often used by the AppleTalk
- Manager during an asynchronous call, and so is locked by the
- AppleTalk Manager. Don’t attempt to unlock or use such a variable.
-
- Each routine description includes a list of the ABusRecord fields affected by the
- routine. The arrow next to each field name indicates whether it’s an input, output,
- or input/output parameter:
-
- Arrow Meaning
- --> Parameter is passed to the routine
- <-- Parameter is returned by the routine
- <-> Parameter is passed to and returned by the routine
-
- _______________________________________________________________________________
-
- »Opening and Closing AppleTalk
-
- •••Refer to Technical Note #224:•••
-
- FUNCTION MPPOpen : OSErr; [Not in ROM]
-
- MPPOpen first checks whether the .MPP driver has already been loaded; if it has,
- MPPOpen does nothing and returns noErr. If MPP hasn’t been loaded, MPPOpen attempts
- to load it into the system heap. If it succeeds, it then initializes the driver’s
- variables and goes through the process of dynamically assigning a node ID to that
- Macintosh. On a Macintosh 512K or XL, it also loads the .ATP driver and NBP code into
- the system heap.
-
- If serial port B isn’t configured for AppleTalk, or is already in use, the .MPP
- driver isn’t loaded and an appropriate result code is returned.
-
- Result codes noErr No error
- portInUse Port B is already in use
- portNotCf Port B not configured for AppleTalk
-
- FUNCTION MPPClose : OSErr; [Not in ROM]
-
- MPPClose removes the .MPP driver, and any data structures associated with it, from
- memory. If the .ATP driver or NBP code were also installed, they’re removed as well.
- MPPClose also returns the use of port B to the Serial Driver.
-
- Warning: Since other co-resident programs may be using AppleTalk, it’s
- strongly recommended that you never use this call. MPPClose will
- completely disable AppleTalk; the only way to restore AppleTalk
- is to call MPPOpen again.
-
- _______________________________________________________________________________
-
- »AppleTalk Link Access Protocol
-
- »Data Structures
-
- ALAP calls use the following ABusRecord fields:
-
- lapProto:
- (lapAddress: LAPAdrBlock; {destination or source node ID}
- lapReqCount: INTEGER; {length of frame data or buffer size in bytes}
- lapActCount: INTEGER; {number of frame data bytes actually received}
- lapDataPtr: Ptr); {pointer to frame data or pointer to buffer}
-
- When an ALAP frame is sent, the lapAddress field indicates the ID of the destination
- node. When an ALAP frame is received, lapAddress returns the ID of the source node.
- The lapAddress field also indicates the ALAP protocol type of the frame:
-
- TYPE LAPAdrBlock = PACKED RECORD
- dstNodeID: Byte; {destination node ID}
- srcNodeID: Byte; {source node ID}
- lapProtType: ABByte {ALAP protocol type}
- END;
-
- When an ALAP frame is sent, lapReqCount indicates the size of the frame data in bytes
- and lapDataPtr points to a buffer containing the frame data to be sent. When an ALAP
- frame is received, lapDataPtr points to a buffer in which the incoming data can be
- stored and lapReqCount indicates the size of the buffer in bytes. The number of bytes
- actually sent or received is returned in the lapActCount field.
-
- Each ALAP frame contains an eight-bit ALAP protocol type in the header. ALAP protocol
- types 128 through 255 are reserved for internal use by ALAP, hence the declaration:
-
- TYPE ABByte = 1..127; {ALAP protocol type}
-
- Warning: Don’t use ALAP protocol type values 1 and 2; they’re reserved
- for use by DDP. Value 3 through 15 are reserved for internal
- use by Apple and also shouldn’t be used.
-
- »Using ALAP
-
- Most programs will never need to call ALAP, because higher-level protocols will
- automatically call it as necessary. If you do want to send a frame directly via ALAP,
- call the LAPWrite function. If you want to read ALAP frames, you have two choices:
-
- • Call LAPOpenProtocol with NIL for protoPtr (see below); this installs
- the default protocol handler provided by the AppleTalk Manager. Then
- call LAPRead to receive frames.
- • Write your own protocol handler, and call LAPOpenProtocol to add it
- to the node’s protocol handler table. The ALAP code will examine every
- incoming frame and send all those with the correct ALAP protocol type
- to your protocol handler. See the section “Protocol Handlers and Socket
- Listeners” for information on how to write a protocol handler.
-
- When your program no longer wants to receive frames with a particular ALAP protocol
- type value, it can call LAPCloseProtocol to remove the corresponding protocol handler
- from the protocol handler table.
-
- »ALAP Routines
-
- FUNCTION LAPOpenProtocol (theLAPType: ABByte;
- protoPtr: Ptr) : OSErr; [Not in ROM]
-
- LAPOpenProtocol adds the ALAP protocol type specified by theLAPType to the
- node’s protocol table. If you provide a pointer to a protocol handler in protoPtr,
- ALAP will send each frame with an ALAP protocol type of theLAPType to that protocol
- handler.
-
- If protoPtr is NIL, the default protocol handler will be used for receiving frames
- with an ALAP protocol type of theLAPType. In this case, to receive a frame you must
- call LAPRead to provide the default protocol handler with a buffer for placing the
- data. If, however, you’ve written your own protocol handler and protoPtr points to
- it, your protocol handler will have the responsibility for receiving the frame and
- it’s not necessary to call LAPRead.
-
- Result codes noErr No error
- lapProtErr Error attaching protocol type
-
- FUNCTION LAPCloseProtocol (theLAPType: ABByte) : OSErr; [Not in ROM]
-
- LAPCloseProtocol removes from the node’s protocol table the specified ALAP protocol
- type, as well as its protocol handler.
-
- Warning: Don’t close ALAP protocol type values 1 or 2. If you close these
- protocol types, DDP will be disabled; once disabled, the only way
- to restore DDP is to restart the system, or to close and then
- reopen AppleTalk.
-
- Result codes noErr No error
- lapProtErr Error detaching protocol type
-
- FUNCTION LAPWrite (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tLAPWrite}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> lapAddress.dstNodeID {destination node ID}
- --> lapAddress.lapProtType {ALAP protocol type}
- --> lapReqCount {length of frame data}
- --> lapDataPtr {pointer to frame data}
-
- LAPWrite sends a frame to another node. LAPReqCount and lapDataPtr specify the length
- and location of the data to send. The lapAddress.lapProtType field indicates the ALAP
- protocol type of the frame and the lapAddress.dstNodeID indicates the node ID of the
- node to which the frame should be sent.
-
- Note: The first two bytes of an ALAP frame’s data must contain the length
- in bytes of that data, including the length bytes themselves.
-
- Result codes noErr No error
- excessCollsns Unable to contact destination node;
- packet not sent
- ddpLenErr ALAP data length too big
- lapProtErr Invalid ALAP protocol type
-
- FUNCTION LAPRead (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tLAPRead}
- <-- abResult {result code}
- --> abUserReference {for your use}
- <-- lapAddress.dstNodeID {destination node ID}
- <-- lapAddress.srcNodeID {source node ID}
- --> lapAddress.lapProtType {ALAP protocol type}
- --> lapReqCount {buffer size in bytes}
- <-- lapActCount {number of frame data bytes actually received}
- --> lapDataPtr {pointer to buffer}
-
- LAPRead receives a frame from another node. LAPReqCount and lapDataPtr specify the
- size and location of the buffer that will receive the frame data. If the buffer isn’t
- large enough to hold all of the incoming frame data, the extra bytes will be discarded
- and buf2SmallErr will be returned. The number of bytes actually received is returned
- in lapActCount. Only frames with ALAP protocol type equal to lapAddress.lapProtType
- will be received. The node IDs of the frame’s source and destination nodes are returned
- in lapAddress.srcNodeID and lapAddress.dstNodeID. You can determine whether the
- packet was broadcast to you by examining the value of lapAddress.dstNodeID—if the
- packet was broadcast it’s equal to 255, otherwise it’s equal to your node ID.
-
- Note: You should issue LAPRead calls only for ALAP protocol types that were
- opened (via LAPOpenProtocol) to use the default protocol handler.
-
- Warning: If you close a protocol type for which there are still LAPRead
- calls pending, the calls will be canceled but the memory occupied
- by their ABusRecords will not be released. For this reason, before
- closing a protocol type, call LAPRdCancel to cancel any pending
- LAPRead calls associated with that protocol type.
-
- Result codes noErr No error
- buf2SmallErr Frame too large for buffer
- readQErr Invalid protocol type or protocol type not
- found in table
-
- FUNCTION LAPRdCancel (abRecord: ABRecHandle) : OSErr; [Not in ROM]
-
- Given the handle to the ABusRecord of a previously made LAPRead call, LAPRdCancel
- dequeues the LAPRead call, provided that a packet satisfying the LAPRead has not
- already arrived. LAPRdCancel returns noErr if the LAPRead call is successfully removed
- from the queue. If LAPRdCancel returns recNotFnd, check the abResult field to verify
- that the LAPRead has been completed and determine its outcome.
-
- Result codes noErr No error
- readQErr Invalid protocol type or protocol type not
- found in table
- recNotFnd ABRecord not found in queue
-
- »Example
-
- This example sends an ALAP packet synchronously and waits asynchronously for a response.
- Assume that both nodes are using a known protocol type (in this case, 73) to receive
- packets, and that the destination node has a node ID of 4.
-
- VAR
- myABRecord: ABRecHandle;
- myBuffer: PACKED ARRAY [0..599] OF CHAR; {buffer for both send and receive}
- myLAPType: Byte;
- errCode, index, dataLen: INTEGER;
- someText: Str255;
- async: BOOLEAN;
-
- BEGIN
- errCode := MPPOpen;
- IF errCode <> noErr THEN
- WRITELN('Error in opening AppleTalk')
- {Maybe serial port B isn't available for use by AppleTalk}
- ELSE
- BEGIN
- {Call Memory Manager to allocate ABusRecord}
- myABRecord := ABRecHandle(NewHandle(lapSize));
- myLAPType := 73;
- {Enter myLAPType into protocol handler table and install default handler to }
- { service frames of that ALAP type. No packets of that ALAP type will be }
- { received until we call LAPRead.}
- errCode := LAPOpenProtocol(myLAPType, NIL);
- IF errCode <> noErr THEN
- WRITELN('Error while opening the protocol type')
- {Have we opened too many protocol types? Remember that DDP uses two of }
- { them.}
- ELSE
- BEGIN
- {Prepare data to be sent}
- someText := 'This data will be in the ALAP data area';
- {The .MPP implementation requires that the first two bytes of the ALAP }
- { data field contain the length of the data, including the length bytes }
- { themselves.}
- dataLen := LENGTH(someText) + 2;
- buffer[0] := CHR(dataLen DIV 256); {high byte of data length}
- buffer[1] := CHR(dataLen MOD 256); {low byte of data length}
- FOR index := 1 TO dataLen - 2 DO {stuff buffer with packet data}
- buffer[index + 1] := someText[index];
- async := FALSE;
- WITH myABRecord^^ DO {fill parameters in the ABusRecord}
- BEGIN
- lapAddress.lapProtType := myLAPType;
- lapAddress.dstNodeID := 4;
- lapReqCount := dataLen;
- lapDataPtr := @buffer;
- END;
- {Send the frame}
- errCode := LAPWrite(myABRecord, async);
- {In the case of a sync call, errCode and the abResult field of }
- { the myABRecord will contain the same result code. We can also }
- { reuse myABRecord, since we know whether the call has completed.}
- IF errCode <> noErr THEN
- WRITELN('Error while writing out the packet')
- {Maybe the receiving node wasn't on-line}
- ELSE
- BEGIN
- {We have sent out the packet and are now waiting for a response. We }
- { issue an async LAPRead call so that we don't “hang” waiting for a }
- { response that may not come.}
- async := TRUE;
- WITH myABRecord^^ DO
- BEGIN
- lapAddress.lapProtType := myLAPType;
- {ALAP type we want to receive }
- lapReqCount := 600; {our buffer is maximum size}
- lapDataPtr := @buffer;
- END;
- errCode := LAPRead(myABRecord, async); {wait for a packet}
- IF errCode <> noErr THEN
- WRITELN('Error while trying to queue up a LAPRead')
- {Was the protocol handler installed correctly?}
- ELSE
- BEGIN
- {We can either sit here in a loop and poll the abResult }
- { field or just exit our code and use the event }
- { mechanism to flag us when the packet arrives.}
- CheckForMyEvent; {your procedure for checking for a network event}
- errCode := LAPCloseProtocol(myLAPType);
- IF errCode <> noErr THEN
- WRITELN('Error while closing the protocol type');
- END;
- END;
- END;
- END;
- END.
-
-
- _______________________________________________________________________________
-
- »Datagram Delivery Protocol
-
- »Data Structures
-
- DDP calls use the following ABusRecord fields:
-
- ddpProto:
- (ddpType: Byte; {DDP protocol type}
- ddpSocket: Byte; {source or listening socket number}
- ddpAddress: AddrBlock; {destination or source socket address}
- ddpReqCount: INTEGER; {length of datagram data or buffer size in bytes}
- ddpActCount: INTEGER; {number of bytes actually received}
- ddpDataPtr: Ptr; {pointer to buffer}
- ddpNodeID: Byte); {original destination node ID}
-
- When a DDP datagram is sent, ddpReqCount indicates the size of the datagram data in
- bytes and ddpDataPtr points to a buffer containing the datagram data. DDPSocket
- specifies the socket from which the datagram should be sent. DDPAddress is the internet
- address of the socket to which the datagram should be sent:
-
- TYPE AddrBlock = PACKED RECORD
- aNet: INTEGER; {network number}
- aNode: Byte; {node ID}
- aSocket: Byte {socket number}
- END;
-
- Note: The network number you specify in ddpAddress.aNet tells MPP whether
- to create a long header (for an internet) or a short header (for a
- local network only). A short DDP header will be sent if ddpAddress.aNet
- is 0 or equal to the network number of the local network.
-
- When a DDP datagram is received, ddpDataPtr points to a buffer in which the incoming
- data can be stored and ddpReqCount indicates the size of the buffer in bytes. The
- number of bytes actually sent or received is returned in the ddpActCount field.
- DDPAddress is the internet address of the socket from which the datagram was sent.
-
- DDPType is the DDP protocol type of the datagram, and ddpSocket specifies the socket
- that will receive the datagram.
-
- Warning: DDP protocol types 1 through 15 and DDP socket numbers 1 through 63
- are reserved by Apple for internal use. Socket numbers 64 through 127
- are available for experimental use. Use of these experimental sockets
- isn’t recommended for commercial products, since there’s no mechanism
- for eliminating conflicting usage by different developers.
-
- »Using DDP
-
- Before it can use a socket, the program must call DDPOpenSocket, which adds a socket
- and its socket listener to the socket table. When a program is finished using a
- socket, call DDPCloseSocket, which removes the socket’s entry from the socket table.
- To send a datagram via DDP, call DDPWrite. To receive datagrams, you have two choices:
-
- • Call DDPOpenSocket with NIL for sktListener (see below); this installs
- the default socket listener provided by the AppleTalk Manager. Then call
- DDPRead to receive datagrams.
- • Write your own socket listener and call DDPOpenSocket to install it. DDP
- will call your socket listener for every incoming datagram for that
- socket; in this case, you shouldn’t call DDPRead. For information on how
- to write a socket listener, see the section “Protocol Handlers and Socket
- Listeners”.
-
- To cancel a previously issued DDPRead call (provided it’s still in the queue), call
- DDPRdCancel.
-
- »DDP Routines
-
- FUNCTION DDPOpenSocket (VAR theSocket: Byte;
- sktListener: Ptr) : OSErr; [Not in ROM]
-
- DDPOpenSocket adds a socket and its socket listener to the socket table. If theSocket
- is nonzero, it must be in the range 64 to 127, and it specifies the socket’s number;
- if theSocket is 0, DDPOpenSocket dynamically assigns a socket number in the range 128
- to 254, and returns it in theSocket. SktListener contains a pointer to the socket
- listener; if it’s NIL, the default listener will be used.
-
- If you’re using the default socket listener, you must then call DDPRead to receive a
- datagram (in order to specify buffer space for the default socket listener). If,
- however, you’ve written your own socket listener and sktListener points to it, your
- listener will provide buffers for receiving datagrams and you shouldn’t use DDPRead
- calls.
-
- DDPOpenSocket will return ddpSktErr if you pass the number of an already opened
- socket, if you pass a socket number greater than 127, or if the socket table is
- full.
-
- Note: The range of static socket numbers 1 through 63 is reserved by Apple
- for internal use. Socket numbers 64 through 127 are available for
- unrestricted experimental use.
-
- Result codes noErr No error
- ddpSktErr Socket error
-
- FUNCTION DDPCloseSocket (theSocket: Byte) : OSErr; [Not in ROM]
-
- DDPCloseSocket removes the entry of the specified socket from the socket table and
- cancels all pending DDPRead calls that have been made for that socket. If you pass a
- socket number of 0, or if you attempt to close a socket that isn’t open, DDPCloseSocket
- will return ddpSktErr.
-
- Result codes noErr No error
- ddpSktErr Socket error
-
- FUNCTION DDPWrite (abRecord: ABRecHandle; doChecksum: BOOLEAN;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tDDPWrite}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> ddpType {DDP protocol type}
- --> ddpSocket {source socket number}
- --> ddpAddress {destination socket address}
- --> ddpReqCount {length of datagram data}
- --> ddpDataPtr {pointer to buffer}
-
- DDPWrite sends a datagram to another socket. DDPReqCount and ddpDataPtr specify the
- length and location of the data to send. The ddpType field indicates the DDP protocol
- type of the frame, and ddpAddress is the complete internet address of the socket to
- which the datagram should be sent. DDPSocket specifies the socket from which the
- datagram should be sent. Datagrams sent over the internet to a node on an AppleTalk
- network different from the sending node’s network have an optional software checksum
- to detect errors that might occur inside the intermediate bridges. If doChecksum is
- TRUE, DDPWrite will compute this checksum; if it’s FALSE, this software checksum
- feature is ignored.
-
- Note: The destination socket can’t be in the same node as the program
- making the DDPWrite call.
-
- Result codes noErr No error
- ddpLenErr Datagram length too big
- ddpSktErr Source socket not open
- noBridgeErr No bridge found
-
- FUNCTION DDPRead (abRecord: ABRecHandle; retCksumErrs: BOOLEAN;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tDDPRead}
- <-- abResult {result code}
- --> abUserReference {for your use}
- <-- ddpType {DDP protocol type}
- --> ddpSocket {listening socket number}
- <-- ddpAddress {source socket address}
- --> ddpReqCount {buffer size in bytes}
- <-- ddpActCount {number of bytes actually received}
- --> ddpDataPtr {pointer to buffer}
- <-- ddpNodeID {original destination node ID}
-
- DDPRead receives a datagram from another socket. The size and location of the buffer
- that will receive the data are specified by ddpReqCount and ddpDataPtr. If the buffer
- isn’t large enough to hold all of the incoming frame data, the extra bytes will be
- discarded and buf2SmallErr will be returned. The number of bytes actually received is
- returned in ddpActCount. DDPSocket specifies the socket to receive the datagram (the
- “listening” socket). The node to which the packet was sent is returned in ddpNodeID;
- if the packet was broadcast ddpNodeID will contain 255. The address of the socket
- that sent the packet is returned in ddpAddress. If retCksumErrs is FALSE, DDPRead
- will discard any packets received with an invalid checksum and inform the caller of
- the error. If retCksumErrs is TRUE, DDPRead will deliver all packets, whether or not
- the checksum is valid; it will also notify the caller when there’s a checksum error.
-
- Note: The sender of the datagram must be in a different node from the
- receiver. You should issue DDPRead calls only for receiving datagrams
- for sockets opened with the default socket listener; see the
- description of DDPOpenSocket.
-
- Note: If the buffer provided isn’t large enough to hold all of the incoming
- frame data (buf2SmallErr), the checksum can’t be calculated; in this
- case, DDPRead will deliver packets even if retCksumErrs is FALSE.
-
- Result codes noErr No error
- buf2SmallErr Datagram too large for buffer
- cksumErr Checksum error
- ddpLenErr Datagram length too big
- ddpSktErr Socket error
- readQErr Invalid socket or socket not found in table
-
- FUNCTION DDPRdCancel (abRecord: ABRecHandle) : OSErr; [Not in ROM]
-
- Given the handle to the ABusRecord of a previously made DDPRead call, DDPRdCancel
- dequeues the DDPRead call, provided that a packet satisfying the DDPRead hasn’t
- already arrived. DDPRdCancel returns noErr if the DDPRead call is successfully removed
- from the queue. If DDPRdCancel returns recNotFnd, check the abResult field of abRecord
- to verify that the DDPRead has been completed and determine its outcome.
-
- Result codes noErr No error
- readQErr Invalid socket or socket not found in table
- recNotFnd ABRecord not found in queue
-
- »Example
-
- This example sends a DDP packet synchronously and waits asynchronously for a response.
- Assume that both nodes are using a known socket number (in this case, 30) to receive
- packets. Normally, you would want to use NBP to look up your destination’s socket
- address.
-
- VAR
- myABRecord: ABRecHandle;
- myBuffer: PACKED ARRAY [0..599] OF CHAR; {buffer for both send and receive}
- mySocket: Byte;
- errCode, index, dataLen: INTEGER;
- someText: Str255;
- async, retCksumErrs, doChecksum: BOOLEAN;
-
- BEGIN
- errCode := MPPOpen;
- IF errCode <> noErr THEN
- WRITELN('Error in opening AppleTalk')
- {Maybe serial port B isn't available for use by AppleTalk}
- ELSE
- BEGIN
- {Call Memory Manager to allocate ABusRecord}
- myABRecord := ABRecHandle(NewHandle(ddpSize));
- mySocket := 30;
- {Add mySocket to socket table and install default socket listener to service }
- { datagrams addressed to that socket. No packets addressed to mySocket will be }
- { received until we call DDPRead. }
- errCode := DDPOpenSocket(mySocket, NIL);
- IF errCode <> noErr THEN
- WRITELN('Error while opening the socket')
- {Have we opened too many socket listeners? Remember that DDP uses two of }
- { them.}
- ELSE
- BEGIN
- {Prepare data to be sent}
- someText := 'This is a sample datagram';
- dataLen := LENGTH(someText);
- FOR index := 0 TO dataLen - 1 DO {stuff buffer with packet data}
- myBuffer[index] := someText[index + 1];
- async := FALSE;
- WITH myABRecord^^ DO {fill the parameters in the ABusRecord}
- BEGIN
- ddpType := 5;
- ddpAddress.aNet := 0; {send on “our” network}
- ddpAddress.aNode := 34;
- ddpAddress.aSocket := mySocket;
- ddpReqCount := dataLen;
- ddpDataPtr := @myBuffer;
- END;
- doChecksum := FALSE;
- {If packet contains a DDP long header, compute checksum and insert it into }
- { the header.}
- errCode := DDPWrite(myABRecord, doChecksum, async); {send packet}
- {In the case of a sync call, errCode and the abResult field of myABRecord }
- { will contain the same result code. We can also reuse myABRecord, since we }
- { know whether the call has completed.}
- IF errCode <> noErr THEN
- WRITELN('Error while writing out the packet')
- {Maybe the receiving node wasn't on-line}
- ELSE
- BEGIN
- {We have sent out the packet and are now waiting for a response. We }
- { issue an async DDPRead call so that we don't “hang” waiting for a }
- { response that may not come. To cancel the async read call, we must }
- { close the socket associated with the call or call DDPRdCancel.}
- async := TRUE;
- retCksumErrs := TRUE; {return packets even if }
- { they have a checksum error}
- WITH myABRecord^^ DO
- BEGIN
- ddpSocket := mySocket;
- ddpReqCount := 600; {our reception buffer is max size}
- ddpDataPtr := @myBuffer;
- END;
- {Wait for a packet asynchronously}
- errCode := DDPRead(myABRecord, retCksumErrs, async);
- IF errCode <> noErr THEN
- WRITELN('Error while trying to queue up a DDPRead')
- {Was the socket listener installed correctly?}
- ELSE
- BEGIN
- {We can either sit here in a loop and poll the }
- { abResult field or just exit our code and use the }
- { event mechanism to flag us when the packet arrives.}
- CheckForMyEvent; {your procedure for checking for a }
- { network event}
- {If there were no errors, a packet is inside the array }
- { mybuffer, the length is in ddpActCount, and the }
- { address of the sending socket is in ddpAddress. }
- { Process the packet received here and report any errors.}
- errCode := DDPCloseSocket(mySocket); {we're done with it}
- IF errCode <> noErr THEN
- WRITELN('Error while closing the socket');
- END;
- END;
- END;
- END;
- END.
-
- _______________________________________________________________________________
-
- »AppleTalk Transaction Protocol
-
- »Data Structures
-
- ATP calls use the following ABusRecord fields:
-
- atpProto:
- (atpSocket: Byte; {listening or responding socket number}
- atpAddress: AddrBlock; {destination or source socket address}
- atpReqCount: INTEGER; {request size or buffer size}
- atpDataPtr: Ptr; {pointer to buffer}
- atpRspBDSPtr: BDSPtr; {pointer to response BDS}
- atpBitMap: BitMapType; {transaction bit map}
- atpTransID: INTEGER; {transaction ID}
- atpActCount: INTEGER; {number of bytes actually received}
- atpUserData: LONGINT; {user bytes}
- atpXO: BOOLEAN; {exactly-once flag}
- atpEOM: BOOLEAN; {end-of-message flag}
- atpTimeOut: Byte; {retry timeout interval in seconds}
- atpRetries: Byte; {maximum number of retries}
- atpNumBufs: Byte; {number of elements in response BDS or number }
- { of response packets sent}
- atpNumRsp: Byte; {number of response packets received or }
- { sequence number}
- atpBDSSize: Byte; {number of elements in response BDS}
- atpRspUData: LONGINT; {user bytes sent or received in transaction }
- { response}
- atpRspBuf: Ptr; {pointer to response message buffer}
- atpRspSize: INTEGER); {size of response message buffer}
-
- The socket receiving the request or sending the response is identified by atpSocket.
- ATPAddress is the address of either the destination or the source socket of a transaction,
- depending on whether the call is sending or receiving data, respectively. ATPDataPtr
- and atpReqCount specify the location and size
- (in bytes) of a buffer that either contains a request or will receive a request. The
- number of bytes actually received in a request is returned in atpActCount. ATPTransID
- specifies the transaction ID. The transaction bit map is contained in atpBitMap, in
- the form:
-
- TYPE BitMapType = PACKED ARRAY[0..7] OF BOOLEAN;
-
- Each bit in the bit map corresponds to one of the eight possible packets in a response.
- For example, when a request is made for which five response packets are expected, the
- bit map sent is binary 00011111 or decimal 31. If the second packet in the response
- is lost, the requesting socket will retransmit the request with a bit map of binary
- 00000010 or decimal 2.
-
- ATPUserData contains the user bytes of an ATP header. ATPXO is TRUE if the transaction
- is to be made with exactly-once service. ATPEOM is TRUE if the response packet is the
- last packet of a transaction. If the number of responses is less than the number that
- were requested, then ATPEOM must also be TRUE. ATPNumRsp contains either the number
- of responses received or the sequence number of a response.
-
- The timeout interval in seconds and the maximum number of times that a request should
- be made are indicated by atpTimeOut and atpRetries, respectively.
-
- Note: Setting atpRetries to 255 will cause the request to be retransmitted
- indefinitely, until a full response is received or the call is canceled.
-
- ATP provides a data structure, known as a response buffer data structure
- (response BDS), for allocating buffer space to receive the datagram(s) of the response.
- A response BDS is an array of one to eight elements. Each BDS element defines the
- size and location of a buffer for receiving one response datagram; they’re numbered 0
- to 7 to correspond to the sequence numbers of the response datagrams.
-
- ATP needs a separate buffer for each response datagram expected, since packets may
- not arrive in the proper sequence. It does not, however, require you to set up and
- use the BDS data structure to describe the response buffers; if you
- don’t, ATP will do it for you. Two sets of calls are provided for both requests and
- responses; one set requires you to allocate a response BDS and the other doesn’t.
-
- Assembly-language note: The two calls that don’t require you to define a BDS
- data structure (ATPRequest and ATPResponse) are
- available in Pascal only.
-
- The number of BDS elements allocated (in other words, the maximum number of datagrams
- that the responder can send) is indicated in the TReq by an eight-bit bit map. The
- bits of this bit map are numbered 0 to 7 (the least significant bit being number 0);
- each bit corresponds to the response datagram with the respective sequence number.
-
- ATPRspBDSPtr and atpBDSSize indicate the location and number of elements in the
- response BDS, which has the following structure:
-
- TYPE BDSElement =
- RECORD
- buffSize: INTEGER; {buffer size in bytes}
- buffPtr: Ptr; {pointer to buffer}
- dataSize: INTEGER; {number of bytes actually received}
- userBytes: LONGINT {user bytes}
- END;
-
- BDSType = ARRAY[0..7] OF BDSElement; {response BDS}
- BDSPtr = ^BDSType;
-
- ATPNumBufs indicates the number of elements in the response BDS that contain information.
- In most cases, you can allocate space for your variables of BDSType statically with a
- VAR declaration. However, you can allocate only the minimum space required by your
- ATP calls by doing the following:
-
- VAR myBDSPtr: BDSPtr;
- . . .
- numOfBDS := 3; {number of elements needed}
- myBDSPtr := BDSPtr(NewPtr(SIZEOF(BDSElement) * numOfBDS));
-
- Note: The userBytes field of the BDSElement and the atpUserData field
- of the ABusRecord represent the same information in the datagram.
- Depending on the ATP call made, one or both of these fields will be used.
-
- »Using ATP
-
- Before you can use ATP on a Macintosh 128K, the .ATP driver must be read from the
- system resource file via an ATPLoad call. The .ATP driver loads itself into the
- application heap and installs a task into the vertical retrace queue.
-
- Warning: When another application starts up, the application heap is
- reinitialized; on a Macintosh 128K, this means that the ATP
- code is lost (and must be reloaded by the next application).
-
- When you’re through using ATP on a Macintosh 128K, call ATPUnload—the system will be
- returned to the state it was in before the .ATP driver was opened.
-
- On a Macintosh 512K or XL, the .ATP driver will have been loaded into the system heap
- either at system startup or upon execution of MPPOpen or ATPLoad. ATPUnload has no
- effect on a Macintosh 512K or XL.
-
- To send a transaction request, call ATPSndRequest or ATPRequest. The .ATP driver will
- automatically select and open a socket through which the request datagram will be
- sent, and through which the response datagrams will be received. The requester must
- specify the full network address (network number, node ID, and socket number) of the
- socket to which the request is to be sent. This socket is known as the responding
- socket, and its address must be known in advance by the requester.
-
- At the responder’s end, before a transaction request can be received, a responding
- socket must be opened, and the appropriate calls be made, to receive a request. To do
- this, the responder first makes an ATPOpenSocket call which allows the responder to
- specify the address (or part of it) of the requesters from whom it’s willing to
- accept transaction requests. Then it issues an ATPGetRequest call to provide ATP with
- a buffer for receiving a request; when a request is received, ATPGetRequest is completed.
- The responder can queue up several ATPGetRequest calls, each of which will be completed
- as requests are received.
-
- Upon receiving a request, the responder performs the requested operation, and then
- prepares the information to be returned to the requester. It then calls ATPSndRsp (or
- ATPResponse) to send the response. Actually, the responder can issue the ATPSndRsp
- call with only part (or none) of the response specified. Additional portions of the
- response can be sent later by calling ATPAddRsp.
-
- The ATPSndRsp and ATPAddRsp calls provide flexibility in the design (and range of
- types) of transaction responders. For instance, the responder may, for some reason,
- be forced to send the responses out of sequence. Also, there might be memory constraints
- that force sending the complete transaction response in parts. Even though eight
- response datagrams might need to be sent, the responder might have only enough memory
- to build one datagram at a time. In this case, it would build the first response
- datagram and call ATPSndRsp to send it. It would then build the second response
- datagram in the same buffer and call ATPAddRsp to send it; and so on, for the third
- through eighth response datagrams.
-
- A responder can close a responding socket by calling ATPCloseSocket. This call cancels
- all pending ATP calls for that socket, such as ATPGetRequest, ATPSndRsp, and ATPResponse.
-
- For exactly-once transactions, the ATPSndRsp and ATPAddRsp calls don’t terminate
- until the entire transaction has completed (that is, the responding end receives a
- release packet, or the release timer has expired).
-
- To cancel a pending, asynchronous ATPSndRequest or ATPRequest call, call ATPReqCancel.
- To cancel a pending, asynchronous ATPSndRsp or ATPResponse call, call ATPRspCancel.
- Pending asynchronous ATPGetRequest calls can be canceled only by issuing the ATPCloseSocket
- call, but that will cancel all outstanding calls for that socket.
-
- •••Refer to Technical Note #250:•••
-
- Warning: You cannot reuse a variable of type ABusRecord passed to an ATP
- routine until the entire transaction has either been completed
- or canceled.
-
- »ATP Routines
-
- FUNCTION ATPLoad : OSErr; [Not in ROM]
-
- •••Refer to Technical Note #224:•••
-
- ATPLoad first verifies that the .MPP driver is loaded and running. If it isn’t,
- ATPLoad verifies that port B is configured for AppleTalk and isn’t in use, and then
- loads MPP into the system heap.
-
- ATPLoad then loads the .ATP driver, unless it’s already in memory. On a Macintosh
- 128K, ATPLoad reads the .ATP driver from the system resource file into the application
- heap; on a Macintosh 512K or XL, ATP is read into the system heap.
-
- Note: On a Macintosh 512K or XL, ATPLoad and MPPOpen perform essentially
- the same function.
-
- Result codes noErr No error
- portInUse Port B is already in use
- portNotCf Port B not configured for AppleTalk
-
- FUNCTION ATPUnload : OSErr; [Not in ROM]
-
- ATPUnload makes the .ATP driver purgeable; the space isn’t actually released by the
- Memory Manager until necessary.
-
- Note: This call applies only to a Macintosh 128K; on a Macintosh 512K
- or Macintosh XL, ATPUnload has no effect.
-
- Result codes noErr No error
-
- FUNCTION ATPOpenSocket (addrRcvd: AddrBlock;
- VAR atpSocket: Byte) : OSErr; [Not in ROM]
-
- ATPOpenSocket opens a socket for the purpose of receiving requests. ATPSocket contains
- the socket number of the socket to open; if it’s 0, a number is dynamically assigned
- and returned in atpSocket. AddrRcvd contains a filter of the sockets from which
- requests will be accepted. A 0 in the network number, node ID, or socket number field
- of the addrRcvd record acts as a “wild card”; for instance, a 0 in the socket number
- field means that requests will be accepted from all sockets in the node(s) specified
- by the network and node fields.
-
- Result codes noErr No error
- tooManySkts Socket table full
- noDataArea Too many outstanding ATP calls
-
- Note: If you’re only going to send requests and receive responses to
- these requests, you don’t need to open an ATP socket. When you
- make the ATPSndRequest or ATPRequest call, ATP automatically
- opens a dynamically assigned socket for that purpose.
-
- FUNCTION ATPCloseSocket (atpSocket: Byte) : OSErr; [Not in ROM]
-
- ATPCloseSocket closes the responding socket whose number is specified by atpSocket.
- It releases the data structures associated with all pending, asynchronous calls
- involving that socket; these pending calls are completed immediately and return the
- result code sktClosed.
-
- Result codes noErr No error
- noDataArea Too many outstanding ATP calls
-
- FUNCTION ATPSndRequest (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tATPSndRequest}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpAddress {destination socket address}
- --> atpReqCount {request size in bytes}
- --> atpDataPtr {pointer to buffer}
- --> atpRspBDSPtr {pointer to response BDS}
- --> atpUserData {user bytes}
- --> atpXO {exactly-once flag}
- <-- atpEOM {end-of-message flag}
- --> atpTimeOut {retry timeout interval in seconds}
- --> atpRetries {maximum number of retries}
- --> atpNumBufs {number of elements in response BDS}
- <-- atpNumRsp {number of response packets actually received}
-
- ATPSndRequest sends a request to another socket. ATPAddress is the internet address
- of the socket to which the request should be sent. ATPDataPtr and atpReqCount specify
- the location and size of a buffer that contains the request information to be sent.
- ATPUserData contains the user bytes for the ATP header.
-
- ATPSndRequest requires you to allocate a response BDS. ATPRspBDSPtr is a pointer to
- the response BDS; atpNumBufs indicates the number of elements in the BDS (this is
- also the maximum number of response datagrams that will be accepted). The number of
- response datagrams actually received is returned in atpNumRsp; if a nonzero value is
- returned, you can examine the response BDS to determine which packets of the transaction
- were actually received. If the number returned is less than requested, one of the
- following is true:
-
- • Some of the packets have been lost and the retry count has been exceeded.
- • ATPEOM is TRUE; this means that the response consisted of fewer packets
- than were expected, but that all packets sent were received (the last
- packet came with the atpEOM flag set).
-
- ATPTimeOut indicates the length of time that ATPSndRequest should wait for a response
- before retransmitting the request. ATPRetries indicates the maximum number of retries
- ATPSndRequest should attempt. ATPXO should be TRUE if you want the request to be part
- of an exactly-once transaction.
-
- ATPSndRequest completes when either the transaction is completed or the retry count
- is exceeded.
-
- Result codes noErr No error
- reqFailed Retry count exceeded
- tooManyReqs Too many concurrent requests
- noDataArea Too many outstanding ATP calls
-
- FUNCTION ATPRequest (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tATPRequest}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpAddress {destination socket address}
- --> atpReqCount {request size in bytes}
- --> atpDataPtr {pointer to buffer}
- <-- atpActCount {number of bytes actually received}
- --> atpUserData {user bytes}
- --> atpXO {exactly-once flag}
- <-- atpEOM {end-of-message flag}
- --> atpTimeOut {retry timeout interval in seconds}
- --> atpRetries {maximum number of retries}
- <-- atpRspUData {user bytes received in transaction response}
- --> atpRspBuf {pointer to response message buffer}
- --> atpRspSize {size of response message buffer}
-
- ATPRequest is functionally analogous to ATPSndRequest. It sends a request to another
- socket, but doesn’t require the caller to set up and use the BDS data structure to
- describe the response buffers. ATPAddress indicates the socket to which the request
- should be sent. ATPDataPtr and atpReqCount specify the location and size of a buffer
- that contains the request information to be sent. ATPUserData contains the user bytes
- to be sent in the request’s ATP header. ATPTimeOut indicates the length of time that
- ATPRequest should wait for a response before retransmitting the request. ATPRetries
- indicates the maximum number of retries ATPRequest should attempt.
-
- To use this call, you must have an area of contiguous buffer space that’s large
- enough to receive all expected datagrams. The various datagrams will be assembled in
- this buffer and returned to you as a complete message upon completion of the transaction.
- The location and size of this buffer are passed in atpRspBuf and atpRspSize. Upon
- completion of the call, the size of the received response message is returned in
- atpActCount. The user bytes received in the ATP header of the first response packet
- are returned in atpRspUData. ATPXO should be TRUE if you want the request to be part
- of an exactly-once transaction.
-
- Although you don’t provide a BDS, ATPRequest in fact creates one and calls the
- .ATP driver (as in an ATPSndRequest call). For this reason, the abRecord fields
- atpRspBDSPtr and atpNumBufs are used by ATPRequest; you should not expect these
- fields to remain unaltered during or after the function’s execution.
-
- For ATPRequest to receive and correctly deliver the response as a single message, the
- responding end must, upon receiving the request (with an ATPGetRequest call), generate
- the complete response as a message in a single buffer and then call ATPResponse.
-
- Note: The responding end could also use ATPSndRsp and ATPAddRsp provided
- that each response packet (except the last one) contains exactly 578
- ATP data bytes; the last packet in the response can contain less than
- 578 ATP data bytes. Also, if this method is used, only the ATP user
- bytes of the first response packet will be delivered to the requester;
- any information in the user bytes of the remaining response packets
- will not be delivered.
-
- ATPRequest completes when either the transaction is completed or the retry count is
- exceeded.
-
- Result codes noErr No error
- reqFailed Retry count exceeded
- tooManyReqs Too many concurrent requests
- sktClosed Socket closed by a cancel call
- noDataArea Too many outstanding ATP calls
-
- FUNCTION ATPReqCancel (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- Given the handle to the ABusRecord of a previously made ATPSndRequest or ATPRequest
- call, ATPReqCancel dequeues the ATPSndRequest or ATPRequest call, provided that the
- call hasn’t already completed. ATPReqCancel returns noErr if the ATPSndRequest or
- ATPRequest call is successfully removed from the queue. If it returns cbNotFound,
- check the abResult field of abRecord to verify that the ATPSndRequest or ATPRequest
- call has completed and determine its outcome.
-
- Result codes noErr No error
- cbNotFound ATP control block not found
-
- FUNCTION ATPGetRequest (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tATPGetRequest}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpSocket {listening socket number}
- <-- atpAddress {source socket address}
- --> atpReqCount {buffer size in bytes}
- --> atpDataPtr {pointer to buffer}
- <-- atpBitMap {transaction bit map}
- <-- atpTransID {transaction ID}
- <-- atpActCount {number of bytes actually received}
- <-- atpUserData {user bytes}
- <-- atpXO {exactly-once flag}
-
- ATPGetRequest sets up the mechanism to receive a request sent by either an ATPSndRequest
- or an ATPRequest call. ATPSocket contains the socket number of the socket that should
- listen for a request; this socket must already have been opened by calling ATPOpenSocket.
- The address of the socket from which the request was sent is returned in atpAddress.
- ATPDataPtr specifies a buffer to store the incoming request; atpReqCount indicates
- the size of the buffer in bytes. The number of bytes actually received in the request
- is returned in atpActCount. ATPUserData contains the user bytes from the ATP header.
- The transaction bit map is returned in atpBitMap. The transaction ID is returned in
- atpTransID. ATPXO will be TRUE if the request is part of an exactly-once transaction.
-
- ATPGetRequest completes when a request is received. To cancel an asynchronous ATPGetRequest
- call, you must call ATPCloseSocket, but this cancels all pending calls involving that
- socket.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
- sktClosed Socket closed by a cancel call
-
- FUNCTION ATPSndRsp (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tATPSdRsp}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpSocket {responding socket number}
- --> atpAddress {destination socket address}
- --> atpRspBDSPtr {pointer to response BDS}
- --> atpTransID {transaction ID}
- --> atpEOM {end-of-message flag}
- --> atpNumBufs {number of response packets being sent}
- --> atpBDSSize {number of elements in response BDS}
-
- ATPSndRsp sends a response to another socket. ATPSocket contains the socket number
- from which the response should be sent and atpAddress contains the internet address
- of the socket to which the response should be sent. ATPTransID must contain the
- transaction ID. ATPEOM is TRUE if the response BDS contains the final packet in a
- transaction composed of a group of packets and the number of packets in the response
- is less than expected. ATPRspBDSPtr points to the buffer data structure containing
- the responses to be sent. ATPBDSSize indicates the number of elements in the response
- BDS, and must be in the range 1 to 8. ATPNumBufs indicates the number of response
- packets being sent with this call, and must be in the range 0 to 8.
-
- Note: In some situations, you may want to send only part (or possibly none)
- of your response message back immediately. For instance, you might be
- requested to send back seven disk blocks, but have only enough internal
- memory to store one block. In this case, set atpBDSSize to 7 (total
- number of response packets), atpNumBufs to 0 (number of response
- packets currently being sent), and call ATPSndRsp. Then as you read
- in one block at a time, call ATPAddRsp until all seven response
- datagrams have been sent.
-
- During exactly-once transactions, ATPSndRsp won’t complete until the release packet
- is received or the release timer expires.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
- noRelErr No release received
- sktClosed Socket closed by a cancel call
- noDataArea Too many outstanding ATP calls
- badBuffNum Bad sequence number
-
- FUNCTION ATPAddRsp (abRecord: ABRecHandle) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tATPAddRsp}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpSocket {responding socket number}
- --> atpAddress {destination socket address}
- --> atpReqCount {buffer size in bytes}
- --> atpDataPtr {pointer to buffer}
- --> atpTransID {transaction ID}
- --> atpUserData {user bytes}
- --> atpEOM {end-of-message flag}
- --> atpNumRsp {sequence number}
-
- ATPAddRsp sends one additional response packet to a socket that has already been sent
- the initial part of a response via ATPSndRsp. ATPSocket contains the socket number
- from which the response should be sent and atpAddress contains the internet address
- of the socket to which the response should be sent. ATPTransID must contain the
- transaction ID. ATPDataPtr and atpReqCount specify the location and size of a buffer
- that contains the information to send; atpNumRsp is the sequence number of the response.
- ATPEOM is TRUE if this response datagram is the final packet in a transaction composed
- of a group of packets. ATPUserData contains the user bytes to be sent in this response
- datagram’s ATP header.
-
- Note: No BDS is needed with ATPAddRsp because all pertinent information
- is passed within the record.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
- badBuffNum Bad sequence number
- noSendResp ATPAddRsp issued before ATPSndRsp
- noDataArea Too many outstanding ATP calls
-
- FUNCTION ATPResponse (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tATPResponse}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpSocket {responding socket number}
- --> atpAddress {destination socket address}
- --> atpTransID {transaction ID)
- --> atpRspUData {user bytes sent in transaction response}
- --> atpRspBuf {pointer to response message buffer}
- --> atpRspSize {size of response message buffer}
-
- ATPResponse is functionally analogous to ATPSndRsp. It sends a response to another
- socket, but doesn’t require the caller to provide a BDS. ATPAddress must contain the
- complete network address of the socket to which the response should be sent (taken
- from the data provided by an ATPGetRequest call). ATPTransID must contain the transaction
- ID. ATPSocket indicates the socket from which the response should be sent (the socket
- on which the corresponding ATPGetRequest was issued). ATPRspBuf points to the buffer
- containing the response message; the size of this buffer must be passed in atpRspSize.
- The four user bytes to be sent in the ATP header of the first response packet are
- passed in atpRspUData. The last packet of the transaction response is sent with the
- EOM flag set.
-
- Although you don’t provide a BDS, ATPResponse in fact creates one and calls the .ATP
- driver (as in an ATPSndRsp call). For this reason, the abRecord fields atpRspBDSPtr
- and atpNumBufs are used by ATPResponse; you should not expect these fields to remain
- unaltered during or after the function’s execution.
-
- During exactly-once transactions ATPResponse won’t complete until the release packet
- is received or the release timer expires.
-
- Warning: The maximum permissible size of the response message is 4624 bytes.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
- noRelErr No release received
- atpLenErr Response too big
- sktClosed Socket closed by a cancel call
- noDataArea Too many outstanding ATP calls
-
- FUNCTION ATPRspCancel (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- Given the handle to the ABusRecord of a previously made ATPSndRsp or ATPResponse
- call, ATPRspCancel dequeues the ATPSndRsp or ATPResponse call, provided that the call
- hasn’t already completed. ATPRspCancel returns noErr if the ATPSndRsp or ATPResponse
- call is successfully removed from the queue. If it returns cbNotFound, check the
- abResult field of abRecord to verify that the ATPSndRsp or ATPResponse call has
- completed and determine its outcome.
-
- Result codes noErr No error
- cbNotFound ATP control block not found
-
- »Example
-
- This example shows the requesting side of an ATP transaction that asks for a 512-byte
- disk block from the responding end. The block number of the file is a byte and is
- contained in myBuffer[0].
-
- VAR
- myABRecord: ABRecHandle;
- myBDSPtr: BDSPtr;
- myBuffer: PACKED ARRAY [0..511] OF CHAR;
- errCode: INTEGER;
- async: BOOLEAN;
-
- BEGIN
- errCode := ATPLoad;
- IF errCode <> noErr THEN
- WRITELN('Error in opening AppleTalk')
- {Maybe serial port B isn't available for use by AppleTalk}
- ELSE
- BEGIN
- {Prepare the BDS; allocate space for a one-element BDS}
- myBDSPtr := BDSPtr(NewPtr(SIZEOF(BDSElement)));
- WITH myBDSPtr^[0] DO
- BEGIN
- buffSize := 512; {size of our buffer used in reception}
- buffPtr := @myBuffer; {pointer to the buffer}
- END;
- {Prepare the ABusRecord}
- myBuffer[0] := CHR(1); {requesting disk block number 1}
- myABRecord := ABRecHandle(NewHandle(atpSize));
- WITH myABRecord^^ DO
- BEGIN
- atpAddress.aNet := 0;
- atpAddress.aNode := 30; {we probably got this from an NBP call}
- atpAddress.aSocket := 15; {socket to send request to}
- atpReqCount := 1; {size of request data field (disk block #)}
- atpDataPtr := @myBuffer; {ptr to request to be sent}
- atpRspBDSPtr := @myBDSPtr;
- atpUserData := 0; {for your use}
- atpXO := FALSE; {at-least-once service}
- atpTimeOut := 5; {5-second timeout}
- atpRetries := 3; {3 retries; request will be sent 4 times max}
- atpNumBufs := 1; {we're only expecting 1 block to be returned}
- END;
- async := FALSE;
- {Send the request and wait for the response}
- errCode := ATPSndRequest(myABRecord, async);
- IF errCode <> noErr THEN
- WRITELN('An error occurred in the ATPSndRequest call')
- ELSE
- BEGIN
- {The disk block requested is now in myBuffer. We can verify }
- { that atpNumRsp contains 1, meaning one response received.}
- . . .
- END;
- END;
- END.
-
- _______________________________________________________________________________
-
- »Name-Binding Protocol
-
- »Data Structures
-
- NBP calls use the following fields:
-
- nbpProto:
- (nbpEntityPtr: EntityPtr; {pointer to entity name}
- nbpBufPtr: Ptr; {pointer to buffer}
- nbpBufSize: INTEGER; {buffer size in bytes}
- nbpDataField: INTEGER; {number of addresses or socket number}
- nbpAddress: AddrBlock; {socket address}
- nbpRetransmitInfo: RetransType); {retransmission information}
-
- When data is sent via NBP, nbpBufSize indicates the size of the data in bytes and
- nbpBufPtr points to a buffer containing the data. When data is received via NBP,
- nbpBufPtr points to a buffer in which the incoming data can be stored and nbpBufSize
- indicates the size of the buffer in bytes. NBPAddress is used in some calls to give
- the internet address of a named entity. The AddrBlock data type is described above
- under “Datagram Delivery Protocol”.
-
- NBPEntityPtr points to a variable of type EntityName, which has the following data
- structure:
-
- TYPE EntityName = RECORD
- objStr: Str32; {object}
- typeStr: Str32; {type}
- zoneStr: Str32 {zone}
- END;
-
- EntityPtr = ^EntityName;
- Str32 = STRING[32];
-
- NBPRetransmitInfo contains information about the number of times a packet should be
- transmitted and the interval between retransmissions:
-
- TYPE RetransType = PACKED RECORD
- retransInterval: Byte; {retransmit interval in }
- { 8-tick units}
- retransCount: Byte {total number of attempts}
- END;
-
- RetransCount contains the total number of times a packet should be transmitted,
- including the first transmission. If retransCount is 0, the packet will be transmitted
- a total of 255 times.
-
- »Using NBP
-
- On a Macintosh 128K, the AppleTalk Manager’s NBP code is read into the application
- heap when any one of the NBP (Pascal) routines is called; you can call the NBPLoad
- function yourself if you want to load the NBP code explicitly. When you’re finished
- with the NBP code and want to reclaim the space it occupies, call NBPUnload. On a
- Macintosh 512K or XL, the NBP code is read in when the .MPP driver is loaded.
-
- Note: When another application starts up, the application heap is
- reinitialized; on a Macintosh 128K, this means that the NBP
- code is lost (and must be reloaded by the next application).
-
- When an entity wants to communicate via an AppleTalk network, it should call NBPRegister
- to place its name and internet address in the names table. When an entity no longer
- wants to communicate on the network, or is being shut down, it should call NBPRemove
- to remove its entry from the names table.
-
- To determine the address of an entity you know only by name, call NBPLookup, which
- returns a list of all entities with the name you specify. Call NBPExtract to extract
- entity names from the list.
-
- If you already know the address of an entity, and want only to confirm that it still
- exists, call NBPConfirm. NBPConfirm is more efficient than NBPLookup in terms of
- network traffic.
-
- »NBP Routines
-
- FUNCTION NBPRegister (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tNBPRegister}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> nbpEntityPtr {pointer to entity name}
- --> nbpBufPtr {pointer to buffer}
- --> nbpBufSize {buffer size in bytes}
- --> nbpAddress.aSocket {socket address}
- --> nbpRetransmitInfo {retransmission information}
-
- NBPRegister adds the name and address of an entity to the node’s names table. NBPEntityPtr
- points to a variable of type EntityName containing the entity’s name. If the name is
- already registered, NBPRegister returns the result code nbpDuplicate. NBPAddress
- indicates the socket for which the name should be registered. NBPBufPtr and nbpBufSize
- specify the location and size of a buffer for NBP to use internally.
-
- While the variable of type EntityName is declared as three 32-byte strings, only the
- actual characters of the name are placed in the buffer pointed to by nbpBufPtr. For
- this reason, nbpBufSize needs only to be equal to the actual length of the name, plus
- an additional 12 bytes for use by NBP.
-
- Warning: This buffer must not be altered or released until the name is
- removed from the names table via an NBPRemove call. If you
- allocate the buffer through a NewHandle call, you must lock
- it as long as the name is registered.
-
- Warning: The zone field of the entity name must be set to the
- meta-character “*”.
-
- Result codes noErr No error
- nbpDuplicate Duplicate name already exists
-
- FUNCTION NBPLookup (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tNBPLookup}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> nbpEntityPtr {pointer to entity name}
- --> nbpBufPtr {pointer to buffer}
- --> nbpBufSize {buffer size in bytes}
- <-> nbpDataField {number of addresses received}
- --> nbpRetransmitInfo {retransmission information}
-
- NBPLookup returns the addresses of all entities with a specified name. NBPEntityPtr
- points to a variable of type EntityName containing the name of the entity whose
- address should be returned. (Meta-characters are allowed in the entity name.) NBPBufPtr
- and nbpBufSize contain the location and size of an area of memory in which the entity
- names and their corresponding addresses should be returned. NBPDataField indicates
- the maximum number of matching names to find addresses for; the actual number of
- addresses found is returned in nbpDataField. NBPRetransmitInfo contains the retry
- interval and the retry count.
-
- When specifying nbpBufSize, for each NBP tuple expected, allow space for the actual
- characters of the name, the address, and four bytes for use by NBP.
-
- Result codes noErr No error
- nbpBuffOvr Buffer overflow
-
- FUNCTION NBPExtract (theBuffer: Ptr; numInBuf: INTEGER; whichOne: INTEGER;
- VAR abEntity: EntityName;
- VAR address: AddrBlock) : OSErr; [Not in ROM]
-
- NBPExtract returns one address from the list of addresses returned by NBPLookup.
- TheBuffer and numInBuf indicate the location and number of tuples in the buffer.
- WhichOne specifies which one of the tuples in the buffer should be returned in the
- abEntity and address parameters.
-
- Result codes noErr No error
- extractErr Can’t find tuple in buffer
-
- FUNCTION NBPConfirm (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tNBPConfirm}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> nbpEntityPtr {pointer to entity name}
- <-- nbpDataField {socket number}
- --> nbpAddress {socket address}
- --> nbpRetransmitInfo {retransmission information}
-
- NBPConfirm confirms that an entity known by name and address still exists (is still
- entered in the names directory). NBPEntityPtr points to a variable of type EntityName
- that contains the name to confirm, and nbpAddress specifies the address to be confirmed.
- (No meta-characters are allowed in the entity name.) NBPRetransmitInfo contains the
- retry interval and the retry count. The socket number of the entity is returned in
- nbpDataField. NBPConfirm is more efficient than NBPLookup in terms of network traffic.
-
- Result codes noErr No error
- nbpConfDiff Name confirmed for different socket
- nbpNoConfirm Name not confirmed
-
- FUNCTION NBPRemove (abEntity: EntityPtr) : OSErr; [Not in ROM]
-
- NBPRemove removes an entity name from the names table of the given entity’s node.
-
- Result codes noErr No error
- nbpNotFound Name not found
-
- FUNCTION NBPLoad : OSErr; [Not in ROM]
-
- On a Macintosh 128K, NBPLoad reads the NBP code from the system resource file into
- the application heap. On a Macintosh 512K or XL, NBPLoad has no effect since the NBP
- code should have already been loaded when the .MPP driver was opened. Normally you’ll
- never need to call NBPLoad, because the AppleTalk Manager calls it when necessary.
-
- Result codes noErr No error
-
- FUNCTION NBPUnload : OSErr; [Not in ROM]
-
- On a Macintosh 128K, NBPUnload makes the NBP code purgeable; the space isn’t actually
- released by the Memory Manager until necessary. On a Macintosh 512K or Macintosh XL,
- NBPUnload has no effect.
-
- Result codes noErr No error
-
- »Example
-
- This example of NBP registers our node as a print spooler, searches for any print
- spoolers registered on the network, and then extracts the information for the first
- one found.
-
- CONST
- mySocket = 20;
-
- VAR
- myABRecord: ABRecHandle;
- myEntity: EntityName;
- entityAddr: AddrBlock;
- nbpNamePtr: Ptr;
- myBuffer: PACKED ARRAY [0..999] OF CHAR;
- errCode: INTEGER;
- async: BOOLEAN;
-
- BEGIN
- errCode := MPPOpen;
- IF errCode <> noErr THEN
- WRITELN('Error in opening AppleTalk')
- {Maybe serial port B isn't available for use by AppleTalk}
- ELSE
- BEGIN
- {Call Memory Manager to allocate ABusRecord}
- myABRecord := ABRecHandle(NewHandle(nbpSize));
- {Set up our entity name to register}
- WITH myEntity DO
- BEGIN
- objStr := 'Gene Station'; {we are called 'Gene Station' }
- typeStr := 'PrintSpooler'; { and are of type 'PrintSpooler'}
- zoneStr := '*';
- {Allocate data space for the entity name (used by NBP)}
- nbpNamePtr := NewPtr(LENGTH(objStr) + LENGTH(typeStr) +
- LENGTH(zoneStr) + 12);
- END;
- {Set up the ABusRecord for the NBPRegister call}
- WITH myABRecord^^ DO
- BEGIN
- nbpEntityPtr := @myEntity;
- nbpBufPtr := nbpNamePtr; {buffer used by NBP internally}
- nbpBufSize := nbpNameBufSize;
- nbpAddress.aSocket := mySocket; {socket to register us on}
- nbpRetransmitInfo.retransInterval := 8; {retransmit every 64 }
- nbpRetransmitInfo.retransCount := 3; { ticks and try 3 times}
- END;
- async := FALSE;
- errCode := NBPRegister(myABRecord, async);
- IF errCode <> noErr THEN
- WRITELN('Error occurred in the NBPRegister call')
- {Maybe the name is already registered somewhere else on the }
- { network.}
- ELSE
- BEGIN
- {Now that we've registered our name, find others of type }
- { 'PrintSpooler'.}
- WITH myEntity DO
- BEGIN
- objStr := '='; {any one of type }
- typeStr := 'PrintSpooler'; { “PrintSpooler” }
- zoneStr := '*'; { in our zone}
- END;
- WITH myABRecord^^ DO
- BEGIN
- nbpEntityPtr := @myEntity;
- nbpBufPtr := @myBuffer; {buffer to place responses in}
- nbpBufSize := SIZEOF(myBuffer);
- {The field nbpDataField, before the NBPLookup call, represents an }
- { approximate number of responses. After the call, nbpDataField }
- { contains the actual number of responses received.}
- nbpDataField := 100; {we want about 100 responses back}
- END;
- errCode := NBPLookup(myABRecord, async); {make sync call}
- IF errCode <> noErr THEN
- WRITELN('An error occurred in the NBPLookup')
- {Did the buffer overflow?}
- ELSE
- BEGIN
- {Get the first reply}
- errCode := NBPExtract(@mybuffer, myABRecord^^.nbpDataField, 1,
- myEntity, entityAddr);
- {The socket address and name of the entity are returned here. If we }
- { want all of them, we'll have to loop for each one in the buffer.}
- IF errCode <> noErr THEN WRITELN('Error in NBPExtract');
- {Maybe the one we wanted wasn't in the buffer}
- END;
- END;
- END;
- END.
-
- _______________________________________________________________________________
-
- »Miscellaneous Routines
-
- FUNCTION GetNodeAddress (VAR myNode,myNet: INTEGER) : OSErr; [Not in ROM]
-
- GetNodeAddress returns the current node ID and network number of the caller. If the
- .MPP driver isn’t installed, it returns noMPPErr. If myNet contains 0, this means
- that a bridge hasn’t yet been found.
-
- Result codes noErr No error
- noMPPErr MPP driver not installed
-
- FUNCTION IsMPPOpen : BOOLEAN; [Not in ROM]
-
- IsMPPOpen returns TRUE if the .MPP driver is loaded and running.
-
- FUNCTION IsATPOpen : BOOLEAN; [Not in ROM]
-
- IsATPOpen returns TRUE if the .ATP driver is loaded and running.
-
- _______________________________________________________________________________
-
-
- æKY New…AppleTalk…Manager…Pascal…Interface
- æC »NEW APPLETALK MANAGER PASCAL INTERFACE AppleTalkManager
- _______________________________________________________________________________
-
- In addition to the interface documented in the previous section, a new parameter
- block–style interface to the AppleTalk Manager is now available for Pascal programmers.
- This new interface, referred to as the preferred interface, is available in addition
- to the Pascal interface described in the previous section, which is referred to as
- the alternate interface. All AppleTalk Manager calls, old and new, are supported by
- the preferred interface.
-
- The alternate interface has not been extended to support the new AppleTalk Manager
- calls. However, the alternate interface provides the only implementation of LAPRead
- and DDPRead. These are higher-level calls not directly supported through the assembly-language
- interface. Developers will wish to use the alternate interface for these calls, and
- also for compatibility with previous applications. In all other cases, it is recommended
- that the new preferred interface be used.
-
- _______________________________________________________________________________
-
- »Using Pascal
-
- All AppleTalk Manager calls in the preferred interface are essentially equivalent to
- the corresponding assembly-language calls. Their form is
-
- FUNCTION MPPCall (pbPtr: Ptr; asyncFlag: BOOLEAN) : OSErr;
-
- where pbPtr points to a device manager parameter block, and asyncFlag is TRUE if the
- call is to be executed asynchronously. Three parameter block types are provided by
- the preferred interface (MPP, ATP, and XPP). The MPP parameter block is shown below.
- The ATP parameter block is shown in the following section, and the XPP parameter
- block is shown in the “Calling the .XPP Driver” section of this document. The field
- names in these parameter blocks are the same as the parameter block offset names
- defined in the assembly-language section (except as documented below). The caller
- fills in the parameter block with the fields as specified in that section and issues
- the appropriate call. The interface issues the actual device manager control call.
-
- On asynchronous calls, the caller may pass a completion routine pointer in the parameter
- block, at offset ioCompletion. This routine will be executed upon completion of the
- call. It is executed at interrupt level and must not make any memory manager calls.
- If it uses application globals, it must ensure that register A5 is set up correctly;
- for details see SetupA5 and RestoreA5 in the Operating System Utilities chapter. If
- no completion routine is desired, ioCompletion should be set to NIL.
-
- Asynchronous calls return control to the caller with result code of noErr as soon as
- they are queued to the driver. This isn’t an indication of successful completion.
- To determine when the call is actually completed, if you don’t want to use a completion
- routine, you can poll the ioResult field; this field is set to 1 when the call is
- made, and receives the actual result code upon completion.
-
- Refer to the appropriate sections of this chapter for the parameter blocks used by
- each MPP and ATP call. As different MPP and ATP calls take different arguments in
- their parameter block, two Pascal variant records have been defined to account for
- all the different cases. These parameter blocks are shown in the sections that
- follow. The first four fields (which are the same for all calls) are automatically
- filled in by the device manager. The csCode and ioRefnum fields are automatically
- filled in by the interface, depending on which call is being made, except in XPP
- where the caller must fill in the ioRefnum. The ioVRefnum field is unused.
-
- There are two fields that at the assembly-language level have more than one name.
- These two fields have been given only one name in the preferred interface. These are
- entityPtr and ntqelPtr, which are both referred to as entityPtr, and atpSocket and
- currBitmap, which are both referred to as atpSocket. These are the only exceptions to
- the naming convention.
-
- »MPP Parameter Block
-
- MPPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OSErr; {result code}
- ioNamePtr: StringPtr; {command result (ATP user bytes) [long]}
- ioVRefNum: INTEGER; {volume reference or drive number}
- ioRefNum: INTEGER; {driver reference number}
- csCode: INTEGER; {call command code AUTOMATICALLY SET}
-
- CASE MPPParmType OF
- LAPWriteParm:
- (filler0:INTEGER;
- wdsPointer:Ptr); {->Write Data Structure}
- AttachPHParm,DetachPHParm:
- (protType:Byte; {ALAP Protocol Type}
- filler1:Byte;
- handler:Ptr); {->protocol handler routine}
- OpenSktParm,CloseSktParm,WriteDDPParm:
- (socket:Byte; {socket number}
- checksumFlag:Byte; {checksum flag}
- listener:Ptr); {->socket listener routine}
- RegisterNameParm,LookupNameParm,ConfirmNameParm,RemoveNameParm:
- (interval:Byte; {retry interval}
- count:Byte; {retry count}
- entityPtr:Ptr; {->names table element or }
- { ->entity name}
- CASE MPPParmType OF
- RegisterNameParm:
- (verifyFlag:Byte; {set if verify needed}
- filler3:Byte);
- LookupNameParm:
- (retBuffPtr:Ptr; {->return buffer}
- retBuffSize:INTEGER; {return buffer size}
- maxToGet:INTEGER; {matches to get}
- numGotten:INTEGER); {matched gotten}
- ConfirmNameParm:
- (confirmAddr:AddrBlock; {->entity}
- newSocket:Byte; {socket number}
- filler4:Byte));
-
- SetSelfSendParm:
- (newSelfFlag:Byte; {self-send toggle flag}
- oldSelfFlag:Byte); {previous self-send state}
- KillNBPParm:
- (nKillQEl:Ptr); {ptr to Q element to cancel}
- END;
-
- »ATP Parameter Block
-
- ATPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OSErr; {result code}
- userData: LONGINT; {ATP user bytes [long]}
- reqTID: INTEGER; {request transaction ID}
- ioRefNum: INTEGER; {driver reference number
- csCode: INTEGER; {Call command code }
- { AUTOMATICALLY SET}
- atpSocket: Byte; {currBitMap or socket number}
- atpFlags: Byte; {control information}
- addrBlock: AddrBlock; {source/dest. socket address}
- reqLength: INTEGER; {request/response length}
- reqPointer: Ptr; {-> request/response data}
- bdsPointer: Ptr; {-> response BDS}
- CASE MPPParmType OF
- SendRequestParm,NSendRequestParm:
- (numOfBuffs:Byte; {numOfBuffs}
- timeOutVal:Byte; {timeout interval}
- numOfResps:Byte; {number responses actually received}
- retryCount:Byte; {number of retries}
- intBuff:INTEGER); {used internally for NSendRequest}
- SendResponseParm:
- (filler0:Byte; {number of responses being sent}
- bdsSize:Byte; {number of BDS elements}
- transID:INTEGER); {transaction ID}
- GetRequestParm:
- (bitMap:Byte; {bit map}
- filler1:Byte);
- AddResponseParm:
- (rspNum:Byte; {sequence number}
- filler2:Byte);
- KillSendReqParm,KillGetReqParm:
- (aKillQEl:Ptr); {ptr to Q element to cancel}
- END;
-
- The following table is a complete list of all the parameter block calls provided by
- the preferred interface.
-
- AppleTalk
- Manager
- Routine Preferred Interface Call
-
- AttachPH Function PAttachPH (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- DetachPH Function PDetachPH (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- WriteLAP Function PWriteLAP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- OpenSkt Function POpenSkt (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- CloseSkt Function PCloseSkt (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- WriteDDP Function PWriteDDP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- RegisterName Function PRegisterName (thePBptr: MPPPBPtr;
- async: BOOLEAN) : OSErr;
- LookupName Function PLookupName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- ConfirmName Function PConfirmName (thePBptr: MPPPBPtr;
- async: BOOLEAN) : OSErr;
- RemoveName Function PRemoveName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- OpenATPSkt Function POpenATPSkt (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- CloseATPSkt Function PCloseATPSkt (thePBptr: ATPPBPtr;
- async: BOOLEAN) : OSErr;
- SendRequest Function PSendRequest (thePBptr: ATPPBPtr;
- async: BOOLEAN) : OSErr;
- GetRequest Function PGetRequest (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- SendResponse Function PSendResponse (thePBptr: ATPPBPtr;
- async: BOOLEAN) : OSErr;
- AddResponse Function PAddResponse(thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- ReltCB Function PRelTCB (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- RelRspCB Function PRelRspCB (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- SetSelfSend Function PSetSelfSend (thePBptr: MPPPBPtr;
- async: BOOLEAN) : OSErr;
- NSendRequest Function PNSendRequest (thePBptr: ATPPBPtr;
- async: BOOLEAN) : OSErr;
- KillSendReq Function PKillSendReq (thePBptr: ATPPBPtr;
- async: BOOLEAN) : OSErr;
- KillGetReq Function PKillGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- KillNBP Function PKillNBP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
- _______________________________________________________________________________
-
- »Building Data Structures
-
- Because it is difficult for Pascal to deal with certain assembly-language structures,
- the preferred interface provides a number of routines for building these structures.
- These routines are summarized below.
-
- PROCEDURE BuildLAPwds (wdsPtr,dataPtr: Ptr;
- destHost,protoType,frameLen: INTEGER);
-
- This routine builds a single-frame write data structure LAP WDS for use with the
- PWriteLAP call. Given a buffer of length frameLen pointed to by dataPtr, it fills in
- the WDS pointed to by wdsPtr and sets the destination node and protocol type as
- indicated by destHost and protoType, respectively. The WDS indicated must contain at
- least two elements.
-
- PROCEDURE BuildDDPwds (wdsPtr,headerPtr,dataPtr: Ptr; destAddress: AddrBlock;
- DDPType : INTEGER; dataLen: INTEGER);
-
- This routine builds a single-frame write data structure DDP WDS, for use with the
- PWriteDDP call. Given a header buffer of at least 17 bytes pointed to by headerPtr
- and a data buffer of length dataLen pointed to by dataPtr, it fills in the WDS pointed
- to by wdsPtr, and sets the destination address and protocol type as indicated by
- destaddress and DDPtype, respectively. The WDS indicated must contain at least 3
- elements.
-
- PROCEDURE NBPSetEntity (buffer: Ptr; nbpObject,nbpType,nbpZone: Str32);
-
- This routine builds an NBP entity structure, for use with the PLookupNBP and PConfirmName
- calls. Given a buffer of at least the size of the EntityName data structure (99
- bytes) pointed to by buffer, this routine sets the indicated object, type, and zone
- in that buffer.
-
- PROCEDURE NBPSetNTE (ntePtr: Ptr; nbpObject,nbpType,nbpZone: Str32;
- Socket: INTEGER);
-
- This routine builds an NBP names table entry, for use with the PRegisterName call.
- Given a names table entry of at least the size of the EntityName data structure plus
- nine bytes (108 bytes) pointed to by ntePtr, this routine sets the indicated object,
- type, zone, and socket in that names table entry.
-
- FUNCTION NBPExtract (theBuffer: Ptr; numInBuf: INTEGER; whichOne: INTEGER; VAR abEntity:
- EntityName; VAR address: AddrBlock) : OSErr;
-
- This routine is provided in the alternate interface, but can be used as provided for
- extracting NBP entity names from a look-up response buffer.
-
- FUNCTION GetBridgeAddress: INTEGER;
-
- This routine returns the current address of a bridge in the low byte, or zero if
- there is none.
-
- FUNCTION BuildBDS (buffPtr,bdsPtr: Ptr; buffSize: INTEGER) : INTEGER;
-
- This routine builds a BDS, for use with the ATP calls. Given a data buffer of length
- buffSize pointed to by buffPtr, it fills in the BDS pointed to by bdsPtr. The buffer
- will be broken up into pieces of maximum size (578 bytes). The user bytes in the BDS
- are not modified by this routine. This routine is provided only as a convenience;
- generally the caller will be able to build the BDS completely from Pascal without
- it.
-
- _______________________________________________________________________________
-
-
- æKY Picking…a…Node…Address…in…the…Server…Range
- æC »PICKING A NODE ADDRESS IN THE SERVER RANGE AppleTalkManager
- _______________________________________________________________________________
-
- Normally upon opening, the node number picked by the AppleTalk manager will be in the
- node number range ($01–$7F). It is possible to indicate that a node number in the
- server range ($80–$FE) is desired. Picking a number in the server range is a more
- time-consuming but more thorough process, and it’s required for server nodes because
- it greatly decreases the possibility of a node number conflict.
-
- To open AppleTalk with a server node number, an extended open call is used. An
- extended open call is indicated by having the immediate bit set in the Open trap
- itself. In the extended open call, the high bit (bit 31) of the extension longword
- field (ioMix) indicates whether a server or workstation node number should be picked.
- Set this bit to 1 to request a server node number. The rest of this field should be
- zero, as should all other unused fields in the queue element. A server node number
- can only be requested on the first Open call to the .MPP driver.
-
- _______________________________________________________________________________
-
-
- æKY Sending…Packets…to…One’s…Own…Node
- æC »SENDING PACKETS TO ONE’S OWN NODE AppleTalkManager
- _______________________________________________________________________________
-
- Upon opening, the ability to send a packet to one’s own node (intranode delivery) is
- disabled. This feature of the AppleTalk Manager can be manipulated through the
- SetSelfSend function. Once enabled, it is possible, at all levels, to send packets
- to entities within one’s own node. An example of where this might be desirable is an
- application sending data to a print spooler that is actually running in the background
- on the same node.
-
- Enabling (or disabling) this feature affects the entire node and should be performed
- with care. For instance, a desk accessory may not expect to receive names from
- within its own node as a response to an NBP look-up; enabling this feature from an
- application could break the desk accessory. All future programs should be written
- with this feature in mind.
-
- FUNCTION PSetSelfSend (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter Block
- --> 26 csCode word Always PSetSelfSend
- --> 28 newSelfFlag byte New SelfSend flag
- <-- 29 oldSelfFlag byte Old SelfSend flag
-
- PSetSelfSend enables or disables the intranode delivery feature of the AppleTalk
- Manager. If newSelfFlag is nonzero, the feature will be enabled; otherwise it will
- be disabled. The previous value of the flag will be returned in oldSelfFlag.
-
- Result Codes noErr No error
-
- _______________________________________________________________________________
-
-
- æKY ATP…Driver…Changes
- æC »ATP DRIVER CHANGES AppleTalkManager
- _______________________________________________________________________________
-
- Changes to the ATP driver include the ability to send an ATP request through a specific
- socket rather than having ATP open a new socket, a new call to abort outstanding
- SendRequest calls, and a new call to abort specific outstanding GetRequest calls.
-
- _______________________________________________________________________________
-
- »Sending an ATP Request Through a Specified Socket
-
- ATP requests can now be sent through client-specified sockets. ATP previously would
- open a dynamic socket, send the request through it, and close the socket when the
- request was completed. The client can now choose to send a request through an already-opened
- socket; this also allows more than one request to be sent per socket. A new call,
- PNSendRequest, has been added for this purpose. The function of the old SendRequest
- call itself remains unchanged.
-
- FUNCTION PNSendRequest (thePBptr: ATPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 18 userData longword User bytes
- <-- 22 reqTID word Transaction ID used in request
- --> 26 csCode word Always sendRequest
- <-> 28 atpSocket byte Socket to send request on
- or current bitmap
- <-> 29 atpFlags byte Control information
- --> 30 addrBlock longword Destination socket address
- --> 34 reqLength word Request size in bytes
- --> 36 reqPointer pointer Pointer to request data
- --> 40 bdsPointer pointer Pointer to response BDS
- --> 44 numOfBuffs byte Number of responses expected
- --> 45 timeOutVal byte Timeout interval
- <-- 46 numOf Resps byte Number of responses received
- <-> 47 retryCount byte Number of retries
- <-- 48 intBuff word Used internally
-
- The PNSendRequest call is functionally equivalent to the SendRequest call, however
- PNSendRequest allows you to specify, in the atpSocket field, the socket through which
- the request is to be sent. This socket must have been previously opened through an
- OpenATPSkt request (otherwise a badATPSkt error will be returned). Note that PNSendRequest
- requires two additional bytes of memory at the end of the parameter block, immediately
- following the retryCount. These bytes are for the internal use of the AppleTalk
- Manager and should not be modified while the PNSendRequest call is active.
-
- There is a machine-dependent limit as to the number of concurrent PNSendRequests that
- can be active on a given socket. If this limit is exceeded, the error tooManyReqs is
- returned.
-
- One additional difference between SendRequest and PNSendRequest is that a PNSendRequest
- can only be aborted by a PKillSendReq call (see below), whereas a SendRequest can be
- aborted by either a RelTCB or KillSendReq call.
-
- Result Codes noErr No error
- reqFailed Retry count exceeded
- tooManyReqs Too many concurrent requests
- noDataArea Too many outstanding ATP calls
- reqAborted Request cancelled by user
-
- _______________________________________________________________________________
-
- »Aborting ATP SendRequests
-
- The RelTCB call is still supported, but only for aborting SendRequests. To abort
- PNSendRequests, a new call, PKillSendReq, has been added. This call will abort both
- SendRequests and PNSendRequests. PKillSendReq’s only argument is the queue element
- pointer of the request to be aborted. The queue element pointer is passed at the
- offset of the PKillSendReq queue element specified by aKillQE1.
-
- FUNCTION PKillSendReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always PKillSendReq
- --> 44 aKillQEl pointer Pointer to queue element
-
- PKillSendReq is functionally equivalent to RelTCB, except that it takes different
- arguments and will abort both SendRequests and PNSendRequests. To abort one of these
- calls, place a pointer to the queue element of the call to abort in aKillQEl and
- issue the PKillSendReq call.
-
- Result Codes noErr No error
- cbNotFound aKillQEl does not point to a SendReq
- or NSendReq queue element
-
- _______________________________________________________________________________
-
- »Aborting ATP GetRequests
-
- ATP GetRequests can now be aborted through the PKillGetReq call. This call looks and
- works just like the PKillSendReq call, and is used to abort a specific GetRequest
- call. Previously it was necessary to close the socket to abort all GetRequest calls
- on the socket.
-
- FUNCTION PKillGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always PKillGetReq
- --> 44 aKillQEl pointer Pointer to queue element
-
- PKillGetReq will abort a specific outstanding GetRequest call (as opposed to closing
- the socket, which aborts all outstanding GetRequests on that socket). The call will
- be completed with a reqAborted error. To abort a GetRequest, place a pointer to the
- queue element of the call to abort in aKillQEl and issue the PKillGetReq call.
-
- Result Codes noErr No error
- cbNotFound aKillQEl does not point to a GetReq
- queue element
-
- _______________________________________________________________________________
-
-
- æKY Name…Binding…Protocol…Changes
- æC »NAME BINDING PROTOCOL CHANGES AppleTalkManager
- _______________________________________________________________________________
-
- Changes to the Name Binding Protocol include supporting multiple concurrent requests
- and a means for aborting an active request.
-
- »Multiple Concurrent NBP Requests
-
- NBP now supports multiple concurrent active requests. Specifically, a number of
- LookupNames, RegisterNames and ConfirmNames can all be active concurrently. The
- maximum number of concurrent requests is machine dependent; if it is exceeded the
- error tooManyReqs will be returned. Active requests can be aborted by the PKillNBP
- call.
-
- »KillNBP function
-
- FUNCTION PKillNBP (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
-
- •••Refer to Technical Note #199:•••
-
- Parameter block
- --> 26 csCode word Always PKillNBP
- --> 28 aKillQEl pointer Pointer to queue element
-
- PKillNBP is used to abort an outstanding LookupName, RegisterName or ConfirmName
- request. To abort one of these calls, place a pointer to the queue element of the
- call to abort in a KillQEl and issue the PKillNBP call. The call will be completed
- with a ReqAborted error.
-
- Result Codes noErr No error
- cbNotFound aKillQEl does not point to a valid
- NBP queue element
-
- _______________________________________________________________________________
-
-
- æKY Variable…Resources
- æC »VARIABLE RESOURCES AppleTalkManager
- _______________________________________________________________________________
-
- The table below lists machine-dependent resources for the different Macintosh system
- configurations. The RAM-based resources are available through the AppleShare Server.
-
- Resource Macintosh Plus RAM-Based Macintosh SE Macintosh II
-
- Protocol
- Handlers 4 8 8 8
-
- Statically
- Assigned
- Sockets 14* 12 12 14
-
- Concurrent
- ATP SendRequests 6 12 12 12
-
- ATP Sockets 6 32 32 126
-
- Concurrent
- ATP Responses 8 16 16 32
-
- Concurrent
- NBP Requests 1 6 6 10
-
- Concurrent
- ASP Sessions N/A 5 10 20
-
- Concurrent
- ATP NSendRequests
- Per Socket ** N/A 9 14 62
-
- * Includes dynamic sockets
- ** Determined dynamically at runtime based on CPU speed.
- N/A : Not Applicable
-
- _______________________________________________________________________________
-
-
- æKY Calling…the…AppleTalk…Manager…from…Assembly…Language
- æC »CALLING THE APPLETALK MANAGER FROM ASSEMBLY LANGUAGE AppleTalkManager
- _______________________________________________________________________________
-
- This section discusses how to use the AppleTalk Manager from assembly language.
- Equivalent Pascal information is given in the preceding section.
-
- All routines make Device Manager Control calls. The description of each routine
- includes a list of the fields needed. Some of these fields are part of the parameter
- block described in the Device Manager chapter; additional fields are provided for the
- AppleTalk Manager.
-
- The number next to each field name indicates the byte offset of the field from the
- start of the parameter block pointed to by A0. An arrow next to each parameter name
- indicates whether it’s an input, output, or input/output parameter:
-
- Arrow Meaning
- --> Parameter is passed to the routine
- <-- Parameter is returned by the routine
- <-> Parameter is passed to and returned by the routine
-
- All Device Manager Control calls return an integer result code of type OSErr in the
- ioResult field. Each routine description lists all of the applicable result codes
- generated by the AppleTalk Manager, along with a short description of what the result
- code means. Lengthier explanations of all the result codes can be found in the summary
- at the end of this chapter. Result codes from other parts of the Operating System may
- also be returned. (See Appendix A for a list of all result codes.)
-
- _______________________________________________________________________________
-
- »Opening AppleTalk
-
- •••Refer to Technical Note #224:•••
-
- Two tests are made at system startup to determine whether the .MPP driver should be
- opened at that time. If port B is already in use, or isn’t configured for AppleTalk,
- .MPP isn’t opened until explicitly requested by an application; otherwise it’s opened
- at system startup.
-
- It’s the application’s responsibility to test the availability of port B before
- opening AppleTalk. Assembly-language programmers can use the Pascal calls MPPOpen and
- ATPLoad to open the .MPP and .ATP drivers.
-
- The global variable SPConfig is used for configuring the serial ports; it’s copied
- from a byte in parameter RAM (which is discussed in the Operating System Utilities
- chapter). The low-order four bits of this variable contain the current configuration
- of port B. The following use types are provided as global constants for testing or
- setting the configuration of port B:
-
- useFree .EQU 0 ;unconfigured
- useATalk .EQU 1 ;configured for AppleTalk
- useAsync .EQU 2 ;configured for the Serial Driver
-
- The application shouldn’t attempt to open AppleTalk unless SPConfig is equal to
- either useFree or useATalk.
-
- A second test involves the global variable PortBUse; the low-order four bits of this
- byte are used to monitor the current use of port B. If PortBUse is negative, the
- program is free to open AppleTalk. If PortBUse is positive, the program should test
- to see whether port B is already being used by AppleTalk; if it is, the low-order
- four bits of PortBUse will be equal to the use type useATalk.
-
- The .MPP driver sets PortBUse to the correct value (useATalk) when it’s opened and
- resets it to $FF when it’s closed. Bits 4-6 of this byte are used for driver-specific
- information; ATP uses bit 4 to indicate whether it’s currently opened:
-
- atpLoadedBit .EQU 4 ;set if ATP is opened
-
- »Example
-
- The following code illustrates the use of the SPConfig and PortBUse variables.
-
- MOVE #-<atpUnitNum+1>,atpRefNum(A0) ;save known ATP refNum in
- ; case ATP not opened
- OpenAbus SUB #ioQElSize,SP ;allocate queue entry
- MOVE.L SP,A0 ;A0 -> queue entry
- CLR.B ioPermssn(A0) ;make sure permission's clear
- MOVE.B PortBUse,D1 ;is port B in use?
- BPL.S @10 ;if so, make sure by AppleTalk
- MOVEQ #portNotCf,D0 ;assume port not configured for AppleTalk
- MOVE.B SPConfig,D1 ;get configuration data
- AND.B #$0F,D1 ;mask it to low 4 bits
- SUBQ.B #useATalk,D1 ;unconfigured or configured for AppleTalk
- BGT.S @30 ;if not, return error
- LEA mppName,A1 ;A1 = address of driver name
- MOVE.L A1,ioFileName(A0) ;set in queue entry
- _Open ;open MPP
- BNE.S @30 ;return error, if it can't load it
- BRA.S @20 ;otherwise, go check ATP
- @10 MOVEQ #portInUse,D0 ;assume port in use error
- AND.B #$0F,D1 ;clear all but use bits
- SUBQ.B #useATalk,D1 ;is AppleTalk using it?
- BNE.S @30 ;if not, then error
- @20 MOVEQ #0,D0 ;assume no error
- BTST #atpLoadedBit,PortBUse ;ATP already open?
- BNE.S @30 ;just return if so
- LEA atpName,A1 ;A1 = address of driver name
- MOVE.L A1,ioFileName(A0) ;set in queue entry
- _Open ;open ATP
- @30 ADD #ioQElSize,SP ;deallocate queue entry
- RTS ;and return
- mppName .BYTE 4 ;length of .MPP driver name
- .ASCII '.MPP' ;name of .MPP driver
- atpName .BYTE 4 ;length of .ATP driver name
- .ASCII '.ATP' ;name of .ATP driver
-
- _______________________________________________________________________________
-
- »AppleTalk Link Access Protocol
-
- »Data Structures
-
- An ALAP frame is composed of a three-byte header, up to 600 bytes of data, and a
- two-byte frame check sequence (Figure 6). You can use the following global constants
- to access the contents of an ALAP header:
-
- lapDstAdr .EQU 0 ;destination node ID
- lapSrcAdr .EQU 1 ;source node ID
- lapType .EQU 2 ;ALAP protocol type
- lapHdSz .EQU 3 ;ALAP header size
-
- •••Refer to Figure 6.•••
-
- Figure 6–ALAP Frame
-
- Two of the protocol handlers in every node are used by DDP. These protocol handlers
- service frames with ALAP protocol types equal to the following global constants:
-
- shortDDP .EQU 1 ;short DDP header
- longDDP .EQU 2 ;long DDP header
-
- When you call ALAP to send a frame, you pass it information about the frame in a
- write data structure, which has the format shown in Figure 7.
-
- •••Refer to Figure 7.•••
-
- Figure 7–Write Data Structure for ALAP
-
- If you specify a destination node ID of 255, the frame will be broadcast to all
- nodes. The byte that’s “used internally” is used by the AppleTalk Manager to store
- the address of the node sending the frame.
-
- »Using ALAP
-
- Most programs will never need to call ALAP, because higher-level protocols will
- automatically call ALAP as necessary. If you do want to send a frame directly via an
- ALAP, call the WriteLAP function. There’s no ReadLAP function in assembly language;
- if you want to read ALAP frames, you must call AttachPH to add your protocol handler
- to the node’s protocol handler table. The ALAP module will examine every incoming
- frame and call your protocol handler for each frame received with the correct ALAP
- protocol. When your program no longer wants to receive frames with a particular ALAP
- protocol type value, it can call DetachPH to remove the corresponding protocol handler
- from the protocol handler table.
-
- See the “Protocol Handlers and Socket Listeners” section for information on how to
- write a protocol handler.
-
- »ALAP Routines
-
- WriteLAP function
-
- Parameter block
- --> 26 csCode word ;always writeLAP
- --> 30 wdsPointer pointer ;write data structure
-
- WriteLAP sends a frame to another node. The frame data and destination of the frame
- are described by the write data structure pointed to by wdsPointer. The first two
- data bytes of an ALAP frame sent to another computer using the AppleTalk Manager must
- indicate the length of the frame in bytes. The ALAP protocol type byte must be in the
- range 1 to 127.
-
- Result codes noErr No error
- excessCollsns No CTS received after 32 RTS’s
- ddpLengthErr Packet length exceeds maximum
- lapProtErr Invalid ALAP protocol type
-
- AttachPH function
-
- Parameter block
- --> 26 csCode word ;always attachPH
- --> 28 protType byte ;ALAP protocol type
- --> 30 handler pointer ;protocol handler
-
- AttachPH adds the protocol handler pointed to by handler to the node’s protocol
- table. ProtType specifies what kind of frame the protocol handler can service. After
- AttachPH is called, the protocol handler is called for each incoming frame whose ALAP
- protocol type equals protType.
-
- Result codes noErr No error
- lapProtErr Error attaching protocol type
-
- DetachPH function
-
- Parameter block
- --> 26 csCode word ;always detachPH
- --> 28 protType byte ;ALAP protocol type
-
- DetachPH removes from the node’s protocol table the specified ALAP protocol type and
- corresponding protocol handler.
-
- Result codes noErr No error
- lapProtErr Error detaching protocol type
-
- _______________________________________________________________________________
-
- »Datagram Delivery Protocol
-
- »Data Structures
-
- A DDP datagram consists of a header followed by up to 586 bytes of actual data
- (Figure 8). The headers can be of two different lengths; they’re identified by the
- following ALAP protocol types:
-
- shortDDP .EQU 1 ;short DDP header
- longDDP .EQU 2 ;long DDP header
-
- •••Refer to Figure 8.•••
-
- Figure 8–DDP Datagram
-
- Long DDP headers (13 bytes) are used for sending datagrams between two or more different
- AppleTalk networks. You can use the following global constants to access the contents
- of a long DDP header:
-
- ddpHopCnt .EQU 0 ;count of bridges passed (4 bits)
- ddpLength .EQU 0 ;datagram length (10 bits)
- ddpChecksum .EQU 2 ;checksum
- ddpDstNet .EQU 4 ;destination network number
- ddpSrcNet .EQU 6 ;source network number
- ddpDstNode .EQU 8 ;destination node ID
- ddpSrcNode .EQU 9 ;source node ID
- ddpDstSkt .EQU 10 ;destination socket number
- ddpSrcSkt .EQU 11 ;source socket number
- ddpType .EQU 12 ;DDP protocol type
-
- The size of a DDP long header is given by the following constant:
-
- ddpHSzLong .EQU ddpType+1
-
- The short headers (five bytes) are used for datagrams sent to sockets within the same
- network as the source socket. You can use the following global constants to access
- the contents of a short DDP header:
-
- ddpLength .EQU 0 ;datagram length
- sDDPDstSkt .EQU ddpChecksum ;destination socket number
- sDDPSrcSkt .EQU sDDPDstSkt+1 ;source socket number
- sDDPType .EQU sDDPSrcSkt+1 ;DDP protocol type
-
- The size of a DDP short header is given by the following constant:
-
- ddpHSzShort .EQU sDDPType+1
-
- The datagram length is a ten-bit field. You can use the following global constant as
- a mask for these bits:
-
- ddpLenMask .EQU $03FF
-
- The following constant indicates the maximum length of a DDP datagram:
-
- ddpMaxData .EQU 586
-
- When you call DDP to send a datagram, you pass it information about the datagram in a
- write data structure with the format shown in Figure 9.
-
- •••Refer to Figure 9.•••
-
- Figure 9–Write Data Structure for DDP
-
- The first seven bytes are used internally for the ALAP header and the DDP datagram
- length and checksum. The other bytes used internally store the network number, node
- ID, and socket number of the socket client sending the datagram.
-
- Warning: The first entry in a DDP write data structure must begin at
- an odd address.
-
- If you specify a node ID of 255, the datagram will be broadcast to all nodes within
- the destination network. A network number of 0 means the local network to which the
- node is connected.
-
- Warning: DDP always destroys the high-order byte of the destination
- network number when it sends a datagram with a short header.
- Therefore, if you want to reuse the first entry of a DDP write
- data structure entry, you must restore the destination network number.
-
- »Using DDP
-
- Before it can use a socket, the program must call OpenSkt, which adds a socket and
- its socket listener to the socket table. When a client is finished using a socket,
- call CloseSkt, which removes the socket’s entry from the socket table. To send a
- datagram via DDP, call WriteDDP. If you want to read DDP datagrams, you must write
- your own socket listener. DDP will send every incoming datagram for that socket to
- your socket listener.
-
- See the “Protocol Handlers and Socket Listeners” section for information on how to
- write a socket listener.
-
- »DDP Routines
-
- OpenSkt function
-
- Parameter block
- --> 26 csCode word ;always openSkt
- <-> 28 socket byte ;socket number
- --> 30 listener pointer ;socket listener
-
- OpenSkt adds a socket and its socket listener to the socket table. If the socket
- parameter is nonzero, it must be in the range 64 to 127, and it specifies the socket’s
- number; if socket is 0, OpenSkt opens a socket with a socket number in the range 128
- to 254, and returns it in the socket parameter. Listener contains a pointer to the
- socket listener.
-
- OpenSkt will return ddpSktErr if you pass the number of an already opened socket, if
- you pass a socket number greater than 127, or if the socket table is full (the socket
- table can hold a maximum of 12 sockets).
-
- Result codes noErr No error
- ddpSktErr Socket error
-
- CloseSkt function
-
- Parameter block
- --> 26 csCode word ;always closeSkt
- --> 28 socket byte ;socket number
-
- CloseSkt removes the entry of the specified socket from the socket table. If you pass
- a socket number of 0, or if you attempt to close a socket that isn’t open, CloseSkt
- will return ddpSktErr.
-
- Result codes noErr No error
- ddpSktErr Socket error
-
- WriteDDP function
-
- Parameter block
- --> 26 csCode word ;always writeDDP
- --> 28 socket byte ;socket number
- --> 29 checksumFlag byte ;checksum flag
- --> 30 wdsPointer pointer ;write data structure
-
- WriteDDP sends a datagram to another socket. WDSPointer points to a write data structure
- containing the datagram and the address of the destination socket. If checksumFlag is
- TRUE, WriteDDP will compute the checksum for all datagrams requiring long headers.
-
- Result codes noErr No error
- ddpLenErr Datagram length too big
- ddpSktErr Socket error
- noBridgeErr No bridge found
-
- _______________________________________________________________________________
-
- »AppleTalk Transaction Protocol
-
- »Data Structures
-
- An ATP packet consists of an ALAP header, DDP header, and ATP header, followed by
- actual data (Figure 10). You can use the following global constants to access the
- contents of an ATP header:
-
- atpControl .EQU 0 ;control information
- atpBitMap .EQU 1 ;bit map
- atpRespNo .EQU 1 ;sequence number
- atpTransID .EQU 2 ;transaction ID
- atpUserData .EQU 4 ;user bytes
-
- The size of an ATP header is given by the following constant:
-
- atpHdSz .EQU 8
-
- •••Refer to Figure 10.•••
-
- Figure 10–ATP Packet
-
- ATP packets are identified by the following DDP protocol type:
-
- atp .EQU 3
-
- The control information contains a function code and various control bits. The function
- code identifies either a TReq, TResp, or TRel packet with one of the following global
- constants:
-
- atpReqCode .EQU $40 ;TReq packet
- atpRspCode .EQU $80 ;TResp packet
- atpRelCode .EQU $C0 ;TRel packet
-
- The send-transmission-status, end-of-message, and exactly-once bits in the control
- information are accessed via the following global constants:
-
- atpSTSBit .EQU 3 ;send-transmission-status bit
- atpEOMBit .EQU 4 ;end-of-message bit
- atpXOBit .EQU 5 ;exactly-once bit
-
- Many ATP calls require a field called atpFlags (Figure 11), which contains the above
- three bits plus the following two bits:
-
- sendChk .EQU 0 ;send-checksum bit
- tidValid .EQU 1 ;transaction ID validity bit
-
- •••Refer to Figure 11.•••
-
- Figure 11–ATPFlags Field
-
- The maximum number of response packets in an ATP transaction is given by the following
- global constant:
-
- atpMaxNum .EQU 8
-
- When you call ATP to send responses, you pass the responses in a response BDS, which
- is a list of up to eight elements, each of which contains the following:
-
- bdsBuffSz .EQU 0 ;size of data to send
- bdsBuffAddr .EQU 2 ;pointer to data
- bdsUserData .EQU 8 ;user bytes
-
- When you call ATP to receive responses, you pass it a response BDS with up to eight
- elements, each in the following format:
-
- bdsBuffSz .EQU 0 ;buffer size in bytes
- bdsBuffAddr .EQU 2 ;pointer to buffer
- bdsDataSz .EQU 6 ;number of bytes actually received
- bdsUserData .EQU 8 ;user bytes
-
- The size of a BDS element is given by the following constant:
-
- bdsEntrySz .EQU 12
-
- ATP clients are identified by internet addresses in the form shown in Figure 12.
-
- •••Refer to Figure 12.•••
-
- Figure 12–Internet Address
-
- »Using ATP
-
- Before you can use ATP on a Macintosh 128K, the .ATP driver must be read from the
- system resource file via a Device Manager Open call. The name of the .ATP driver is
- '.ATP' and its reference number is –11. When the .ATP driver is opened, it reads its
- ATP code into the application heap and installs a task into the vertical retrace
- queue.
-
- Warning: When another application starts up, the application heap is
- reinitialized; on a Macintosh 128K, this means that the ATP
- code is lost (and must be reloaded by the next application).
-
- When you’re through using ATP on a Macintosh 128K, call the Device Manager Close
- routine—the system will be returned to the state it was in before the
- .ATP driver was opened.
-
- On a Macintosh 512K or XL, the .ATP driver will have been loaded into the system heap
- either at system startup or upon execution of a Device Manager Open call loading MPP.
- You shouldn’t close the .ATP driver on a Macintosh 512K or XL; AppleTalk expects it
- to remain open on these systems.
-
- To send a request to another socket and get a response, call SendRequest. The call
- terminates when either an entire response is received or a specified retry timeout
- interval elapses. To open a socket for the purpose of responding to requests, call
- OpenATPSkt. Then call GetRequest to receive a request; when a request is received,
- the call is completed. After receiving and servicing a request, call SendResponse to
- return response information. If you cannot or do not want to send the entire response
- all at once, make a SendResponse call to send some of the response, and then call
- AddResponse later to send the remainder of the response. To close a socket opened for
- the purpose of sending responses, call CloseATPSkt.
-
- During exactly-once transactions, SendResponse doesn’t terminate until the transaction
- is completed via a TRel packet, or the retry count is exceeded.
-
- Warning: Don’t modify the parameter block passed to an ATP call until
- the call is completed.
-
- »ATP Routines
-
- OpenATPSkt function
-
- Parameter block
- --> 26 csCode word ;always openATPSkt
- <-> 28 atpSocket byte ;socket number
- --> 30 addrBlock long word ;socket request specification
-
- OpenATPSkt opens a socket for the purpose of receiving requests. ATPSocket contains
- the socket number of the socket to open. If it’s 0, a number is dynamically assigned
- and returned in atpSocket. AddrBlock contains a specification of the socket addresses
- from which requests will be accepted. A 0 in the network number, node ID, or socket
- number field of addrBlock means that requests will be accepted from every network,
- node, or socket, respectively.
-
- Result codes noErr No error
- tooManySkts Too many responding sockets
- noDataArea Too many outstanding ATP calls
-
- CloseATPSkt function
-
- Parameter block
- --> 26 csCode word ;always closeATPSkt
- --> 28 atpSocket byte ;socket number
-
- CloseATPSkt closes the socket whose number is specified by atpSocket, for the purpose
- of receiving requests.
-
- Result codes noErr No error
- noDataArea Too many outstanding ATP calls
-
- SendRequest function
-
- Parameter block
- --> 18 userData long word ;user bytes
- <-- 22 reqTID word ;transaction ID used in request
- --> 26 csCode word ;always sendRequest
- <-- 28 currBitMap byte ;bit map
- <-> 29 atpFlags byte ;control information
- --> 30 addrBlock long word ;destination socket address
- --> 34 reqLength word ;request size in bytes
- --> 36 reqPointer pointer ;pointer to request data
- --> 40 bdsPointer pointer ;pointer to response BDS
- --> 44 numOfBuffs byte ;number of responses expected
- --> 45 timeOutVal byte ;timeout interval
- <-- 46 numOfResps byte ;number of responses received
- <-> 47 retryCount byte ;number of retries
-
- SendRequest sends a request to another socket and waits for a response. UserData
- contains the four user bytes. AddrBlock indicates the socket to which the request
- should be sent. ReqLength and reqPointer contain the size and location of the request
- to send. BDSPointer points to a response BDS where the responses are to be returned;
- numOfBuffs indicates the number of responses requested. The number of responses
- received is returned in numOfResps. If a nonzero value is returned in numOfResps, you
- can examine currBitMap to determine which packets of the transaction were actually
- received and to detect pieces for higher-level recovery, if desired.
-
- TimeOutVal indicates the number of seconds that SendRequest should wait for a response
- before resending the request. RetryCount indicates the maximum number of retries
- SendRequest should attempt. The end-of-message flag of atpFlags will be set if the
- EOM bit is set in the last packet received in a valid response sequence. The exactly-once
- flag should be set if you want the request to be part of an exactly-once transaction.
-
- To cancel a SendRequest call, you need the transaction ID; it’s returned in reqTID.
- You can examine reqTID before the completion of the call, but its contents are valid
- only after the tidValid bit of atpFlags has been set.
-
- SendRequest completes when either an entire response is received or the retry count
- is exceeded.
-
- Note: The value provided in retryCount will be modified during SendRequest
- if any retries are made. This field is used to monitor the number of
- retries; for each retry, it’s decremented by 1.
-
- Result codes noErr No error
- reqFailed Retry count exceeded
- tooManyReqs Too many concurrent requests
- noDataArea Too many outstanding ATP calls
- reqAborted Request canceled by user
-
- GetRequest function
-
- Parameter block
- <-- 18 userData long word ;user bytes
- --> 26 csCode word ;always getRequest
- --> 28 atpSocket byte ;socket number
- <-- 29 atpFlags byte ;control information
- <-- 30 addrBlock long word ;source of request
- <-> 34 reqLength word ;request buffer size
- --> 36 reqPointer pointer ;pointer to request buffer
- <-- 44 bitMap byte ;bit map
- <-- 46 transID word ;transaction ID
-
- GetRequest sets up the mechanism to receive a request sent by a SendRequest call.
- UserData returns the four user bytes from the request. ATPSocket contains the socket
- number of the socket that should listen for a request. The internet address of the
- socket from which the request was sent is returned in addrBlock. ReqLength and reqPointer
- indicate the size (in bytes) and location of a buffer to store the incoming request.
- The actual size of the request is returned in reqLength. The transaction bit map and
- transaction ID will be returned in bitMap and transID. The exactly-once flag in
- atpFlags will be set if the request is part of an exactly-once transaction.
-
- GetRequest completes when a request is received.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
-
- SendResponse function
-
- Parameter block
- <-- 18 userData long word ;user bytes from TRel
- <-- 22 reqTID word ;transaction ID used in request
- --> 26 csCode word ;always sendResponse
- --> 28 atpSocket byte ;socket number
- --> 29 atpFlags byte ;control information
- --> 30 addrBlock long word ;response destination
- --> 40 bdsPointer pointer ;pointer to response BDS
- --> 44 numOfBuffs byte ;number of response packets being sent
- --> 45 bdsSize byte ;BDS size in elements
- --> 46 transID word ;transaction ID
-
- SendResponse sends a response to a socket. If the response was part of an exactly-once
- transaction, userData will contain the user bytes from the TRel packet. ATPSocket
- contains the socket number from which the response should be sent. The end-of-message
- flag in atpFlags should be set if the response contains the final packet in a transaction
- composed of a group of packets and the number of responses is less than requested.
- AddrBlock indicates the address of the socket to which the response should be sent.
- BDSPointer points to a response BDS containing room for the maximum number of responses
- to be sent; bdsSize contains this maximum number. NumOfBuffs contains the number of
- response packets to be sent in this call; you may wish to make AddResponse calls to
- complete the response. TransID indicates the transaction ID of the associated request.
-
- During exactly-once transactions, SendResponse doesn’t complete until either a TRel
- packet is received from the socket that made the request, or the retry count is
- exceeded.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
- noRelErr No release received
- noDataArea Too many outstanding ATP calls
- badBuffNum Sequence number out of range
-
- AddResponse function
-
- Parameter block
- --> 18 userData long word ;user bytes
- --> 26 csCode word ;always addResponse
- --> 28 atpSocket byte ;socket number
- --> 29 atpFlags byte ;control information
- --> 30 addrBlock long word ;response destination
- --> 34 reqLength word ;response size
- --> 36 reqPointer pointer ;pointer to response
- --> 44 rspNum byte ;sequence number
- --> 46 transID word ;transaction ID
-
- AddResponse sends an additional response packet to a socket that has already been
- sent the initial part of a response via SendResponse. UserData contains the four user
- bytes. ATPSocket contains the socket number from which the response should be sent.
- The end-of-message flag in atpFlags should be set if this response packet is the
- final packet in a transaction composed of a group of packets and the number of responses
- is less than requested. AddrBlock indicates the socket to which the response should
- be sent. ReqLength and reqPointer contain the size (in bytes) and location of the
- response to send; rspNum indicates the sequence number of the response (in the range
- 0 to 7). TransID must contain the transaction ID.
-
- Warning: If the transaction is part of an exactly-once transaction, the
- buffer used in the AddResponse call must not be altered or
- released until the corresponding SendResponse call has completed.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
- noSendResp AddResponse issued before SendResponse
- badBuffNum Sequence number out of range
- noDataArea Too many outstanding ATP calls
-
- RelTCB function
-
- Parameter block
- --> 26 csCode word ;always relTCB
- --> 30 addrBlock long word ;destination of request
- --> 46 transID word ;transaction ID of request
-
- RelTCB dequeues the specified SendRequest call and returns the result code reqAborted
- for the aborted call. The transaction ID can be obtained from the reqTID field of the
- SendRequest queue entry; see the description of SendRequest for details.
-
- Result codes noErr No error
- cbNotFound ATP control block not found
- noDataArea Too many outstanding ATP calls
-
- RelRspCB function
-
- Parameter block
- --> 26 csCode word ;always relRspCB
- --> 28 atpSocket byte ;socket number that request was received on
- --> 30 addrBlock long word ;source of request
- --> 46 transID word ;transaction ID of request
-
- In an exactly-once transaction, RelRspCB cancels the specified SendResponse, without
- waiting for the release timer to expire or a TRel packet to be received. No error is
- returned for the SendResponse call. Whan called to cancel a transaction that isn’t
- using exactly-once service, RelRspCB returns cbNotFound. The transaction ID can be
- obtained from the reqTID field of the SendResponse queue entry; see the description
- of SendResponse for details.
-
- Result codes noErr No error
- cbNotFound ATP control block not found
-
- _______________________________________________________________________________
-
- »Name-Binding Protocol
-
- »Data Structures
-
- The first two bytes in the NBP header (Figure 13) indicate the type of the packet,
- the number of tuples in the packet, and an NBP packet identifier. You can use the
- following global constants to access these bytes:
-
- nbpControl .EQU 0 ;packet type
- nbpTCount .EQU 0 ;tuple count
- nbpID .EQU 1 ;packet identifier
- nbpTuple .EQU 2 ;start of first tuple
-
- •••Refer to Figure 13.•••
-
- Figure 13–NBP Packet
-
- NBP packets are identified by the following DDP protocol type:
-
- nbp .EQU 2
-
- NBP uses the following global constants in the nbpControl field to identify NBP
- packets:
-
- brRq .EQU 1 ;broadcast request
- lkUp .EQU 2 ;lookup request
- lkUpReply .EQU 3 ;lookup reply
-
- NBP entities are identified by internet address in the form shown in Figure 14 below.
- Entities are also identified by tuples, which include both an internet address and an
- entity name. You can use the following global constants to access information in
- tuples:
-
- tupleNet .EQU 0 ;network number
- tupleNode .EQU 2 ;node ID
- tupleSkt .EQU 3 ;socket number
- tupleEnum .EQU 4 ;used internally
- tupleName .EQU 5 ;entity name
-
- The meta-characters in an entity name can be identified with the following global
- constants:
-
- equals .EQU '=' ;“wild-card” meta-character
- star .EQU '*' ;“this zone” meta-character
-
- •••Refer to Figure 14.•••
-
- Figure 14–Names Table Entry
-
- The maximum number of tuples in an NBP packet is given by the following global constant:
-
- tupleMax .EQU 15
-
- Entity names are mapped to sockets via the names table. Each entry in the names table
- has the structure shown in Figure 14.
-
- You can use the following global constants to access some of the elements of a names
- table entry:
-
- ntLink .EQU 0 ;pointer to next entry
- ntTuple .EQU 4 ;tuple
- ntSocket .EQU 7 ;socket number
- ntEntity .EQU 9 ;entity name
-
- The socket number of the names information socket is given by the following global
- constant:
-
- nis .EQU 2
-
- »Using NBP
-
- On a Macintosh 128K, before calling any other NBP routines, call the LoadNBP function,
- which reads the NBP code from the system resource file into the application heap.
- (The NBP code is part of the .MPP driver, which has a driver reference number of
- –10.) When you’re finished with NBP and want to reclaim the space its code occupies,
- call UnloadNBP. On a Macintosh 512K or XL, the NBP code is read in when the .MPP
- driver is loaded.
-
- Warning: When an application starts up, the application heap is
- reinitialized; on a Macintosh 128K, this means that the
- NBP code is lost (and must be reloaded by the next application).
-
- When an entity wants to communicate via an AppleTalk network, it should call RegisterName
- to place its name and internet address in the names table. When an entity no longer
- wants to communicate on the network, or is being shut down, it should call RemoveName
- to remove its entry from the names table.
-
- To determine the address of an entity you know only by name, call LookupName, which
- returns a list of all entities with the name you specify. If you already know the
- address of an entity, and want only to confirm that it still exists, call ConfirmName.
- ConfirmName is more efficient than LookupName in terms of network traffic.
-
- »NBP Routines
-
- RegisterName function
-
- Parameter block
- --> 26 csCode word ;always registerName
- --> 28 interval byte ;retry interval
- <-> 29 count byte ;retry count
- --> 30 ntQElPtr pointer ;names table element pointer
- --> 34 verifyFlag byte ;set if verify needed
-
- RegisterName adds the name and address of an entity to the node’s names table. NTQElPtr
- points to a names table entry containing the entity’s name and internet address (in
- the form shown in Figure 14 above). Meta-characters aren’t allowed in the object and
- type fields of the entity name; the zone field, however, must contain the meta-character
- “*”. If verifyFlag is TRUE, RegisterName checks on the network to see if the name is
- already in use, and returns a result code of nbpDuplicate if so. Interval and count
- contain the retry interval in eight-tick units and the retry count. When a retry is
- made, the count field is modified.
-
- •••Refer to Technical Note #225:•••
-
- Warning: The names table entry passed to RegisterName remains the
- property of NBP until removed from the names table. Don’t
- attempt to remove or modify it. If you’ve allocated memory
- using a NewHandle call, you must lock it as long as the name
- is registered.
-
- Warning: VerifyFlag should normally be set before calling RegisterName.
-
- Result codes noErr No error
- nbpDuplicate Duplicate name already exists
- nbpNISErr Error opening names information socket
-
- LookupName function
-
- Parameter block
- --> 26 csCode word ;always lookupName
- --> 28 interval byte ;retry interval
- <-> 29 count byte ;retry count
- --> 30 entityPtr pointer ;pointer to entity name
- --> 34 retBuffPtr pointer ;pointer to buffer
- --> 38 retBuffSize word ;buffer size in bytes
- --> 40 maxToGet word ;matches to get
- <-- 42 numGotten word ;matches found
-
- LookupName returns the addresses of all entities with a specified name. EntityPtr
- points to the entity’s name (in the form shown in Figure 14 above). Meta-characters
- are allowed in the entity name. RetBuffPtr and retBuffSize contain the location and
- size of an area of memory in which the tuples describing the entity names and their
- corresponding addresses should be returned. MaxToGet indicates the maximum number of
- matching names to find addresses for; the actual number of addresses found is returned
- in numGotten. Interval and count contain the retry interval and the retry count.
- LookupName completes when either the number of matches is equal to or greater than
- maxToGet, or the retry count has been exceeded. The count field is decremented for
- each retransmission.
-
- Note: NumGotten is first set to 0 and then incremented with each match
- found. You can test the value in this field, and can start examining
- the received addresses in the buffer while the lookup continues.
-
- Result codes noErr No error
- nbpBuffOvr Buffer overflow
-
- ConfirmName function
-
- Parameter block
- --> 26 csCode word ;always confirmName
- --> 28 interval byte ;retry interval
- <-> 29 count byte ;retry count
- --> 30 entityPtr pointer ;pointer to entity name
- --> 34 confirmAddr pointer ;entity address
- <-- 38 newSocket byte ;socket number
-
- ConfirmName confirms that an entity known by name and address still exists (is still
- entered in the names directory). EntityPtr points to the entity’s name
- (in the form shown in Figure 14 above). ConfirmAddr specifies the address to confirmed.
- No meta-characters are allowed in the entity name. Interval and count contain the
- retry interval and the retry count. The socket number of the entity is returned in
- newSocket. ConfirmName is more efficient than LookupName in terms of network traffic.
-
- Result codes noErr No error
- nbpConfDiff Name confirmed for different socket
- nbpNoConfirm Name not confirmed
-
- RemoveName function
-
- Parameter block
- --> 26 csCode word ;always removeName
- --> 30 entityPtr pointer ;pointer to entity name
-
- RemoveName removes an entity name from the names table of the given entity’s node.
-
- Result codes noErr No error
- nbpNotFound Name not found
-
- LoadNBP function
-
- Parameter block
- --> 26 csCode word ;always loadNBP
-
- On a Macintosh 128K, LoadNBP reads the NBP code from the system resource file into
- the application heap; on a Macintosh 512K or XL it has no effect.
-
- Result codes noErr No error
-
- UnloadNBP function
-
- Parameter block
- --> 26 csCode word ;always unloadNBP
-
- On a Macintosh 128K, UnloadNBP makes the NBP code purgeable; the space isn’t actually
- released by the Memory Manager until necessary. On a Macintosh 512K or XL, UnloadNBP
- has no effect.
-
- Result codes noErr No error
-
- _______________________________________________________________________________
-
-
- æKY Extended…Protocol…Package…Driver
- æC »EXTENDED PROTOCOL PACKAGE DRIVER AppleTalkManager
- _______________________________________________________________________________
-
- The Extended Protocol Package (XPP) driver is intended to implement several AppleTalk
- communication protocols in the same package for ease of use. The
- .XPP driver currently consists of two modules that operate on two levels: the low-level
- module implements the workstation side of AppleTalk Session Protocol, and the high-level
- module implements a small portion of the workstation side of the AppleTalk Filing
- Protocol.
-
- This driver adds functionality to the AppleTalk manager by providing services additional
- to those provided in the .MPP and .ATP drivers. Figure 2 shows the Macintosh AppleTalk
- drivers and the protocols accessible through each driver.
-
- The .XPP driver maps an AFP call from the client workstation into one or more ASP
- calls. .XPP provides one client-level call for AFP.
-
- The implementation of AFP in the .XPP driver is very limited. Most calls are a very
- simple one-to-one mapping from an AFP call to an ASP command without any interpretation
- of the syntax of the AFP command by the .XPP driver. Refer to the “Mapping AFP
- Commands” section of this chapter for further information.
-
- _______________________________________________________________________________
-
- »Version
-
- The .XPP driver supports ASP Version (hex) $100, as described in Inside AppleTalk.
-
- _______________________________________________________________________________
-
- »Error Reporting
-
- Errors are returned by the .XPP driver in the ioResult field of the Device Manager
- Control calls.
-
- The error conditions reported by the .XPP driver may represent the unsuccessful
- completion of a routine in more than just one process involved in the interaction of
- the session. System-level, .XPP driver, AppleTalk, and server errors can all turn
- up in the ioResult field.
-
- AFP calls return codes indicating the unsuccessful completion of AFP commands in the
- Command Result field of the parameter block (described below).
-
- An application using the .XPP driver should respond appropriately to error conditions
- reported from the different parts of the interaction. As shown in Figure 3, the
- following errors can be returned in the ioResult field:
-
- 1. System-level errors
-
- System errors returned by the .XPP driver indicate such conditions
- as the driver not being open or a specific system call not being
- supported. For a complete list of result codes returned by the
- Macintosh system software, refer to Appendix A.
-
- 2. XPP errors (for example, “Session not opened”)
-
- The .XPP driver can also return errors resulting from its own
- activity (for example, the referenced session isn’t open). The
- possible .XPP driver errors returned are listed in the .XPP driver
- results codes section with each function that can return the code.
-
- 3. AppleTalk Errors (returned from lower-level protocols)
-
- .XPP may also return errors from lower-level protocols (for example,
- “Socket not open”). Possible error conditions and codes are described
- elsewhere in this chapter.
-
- 4. An ASP-specific error could be returned from an ASP server in
- response to a failed OpenSession call. Errors of this type, returned
- by the server to the workstation, are documented both in Inside
- AppleTalk, section 11, “AppleTalk Session Protocol”, and in the .XPP
- driver results code section of this chapter.
-
- 5. The AppleTalk Filing Protocol defines errors that are returned from
- the server to the workstation client. These errors are returned in
- the cmdResult field of the parameter block (error type 5 in Figure 15).
- This field is valid if no system-level error is returned by the call.
- Note that at the ASP level, the cmdResult field is client-defined data
- and may not be an error code.
-
- •••Refer to Figure 15.•••
-
- Figure 15–Error Reporting
-
- _______________________________________________________________________________
-
- ».XPP Driver Functions Overview
-
- The paragraphs below describe the implementation of ASP in the .XPP driver. For more
- detailed information about ASP, refer to Inside AppleTalk, Section 11, “AppleTalk
- Session Protocol (ASP)”.
-
- »Using AppleTalk Name Binding Protocol
-
- A server wishing to advertise its service on the AppleTalk network calls ATP to open
- an ATP responding socket known as the session listening socket (SLS). The server
- then calls the Name Binding Protocol (NBP) to register a name on this socket. At
- this point, the server calls the server side of ASP to pass it the address of the
- SLS. Then, the server starts listening on the SLS for session opening requests
- coming over the network.
-
- »Opening and Closing Sessions
-
- When a workstation wishes to access a server, the workstation must call NBP to discover
- the SLS for that server. Then the workstation calls ASP to open a session with that
- server.
-
- After determining the SLS (address) of the server, the workstation client issues an
- OpenSession (or AFPLogin) call to open a session with that server. As a result of
- this call, ASP sends a special OpenSession packet (an ATP request) to the SLS; this
- packet carries the address of a workstation socket for use in the session. This
- socket is referred to as the workstation session socket (WSS). If the server is
- unable to set up the session, it returns an error. If the request is successful, the
- server returns no error, and the session is opened. The open session packet also
- contains a version number so that both ends can verify that they are speaking the
- same version of ASP.
-
- The AbortOS function can be used to abort an outstanding OpenSession request before
- it has completed.
-
- The workstation client closes the session by issuing a CloseSession (or AFPLogout).
- The CloseSession call aborts any calls that are active on the session and closes the
- session. The session can also be closed by the server or by ASP itself, such as when
- one end of the session fails. The CloseAll call (which should be used with care)
- aborts every session that the driver has active.
-
- »Session Maintenance
-
- A session will remain open until it is explicitly terminated by the ASP client at
- either end or until one of the sessions ends, fails, or becomes unreachable.
-
- »Commands on an Open Session
-
- Once a session has been opened, the workstation client can send a sequence of commands
- over the session to the server end. The commands are delivered in the same order as
- they are issued at the workstation end, and replies to the commands are returned to
- the workstation end.
-
- Three types of commands can be made on an open session. These commands are UserCommand,
- UserWrite, and AFPCall functions described in the following paragraphs.
-
- UserCommand calls are similar to ATP requests. The workstation client sends a command
- (included in a variable size command block) to the server client requesting it to
- perform a particular function and send back a variable size command reply. Examples
- of such commands vary from a request to open a particular file on a file server, to
- reading a certain range of bytes from a device. In the first case, a small amount of
- reply data is returned; in the second case a multiple-packet reply might be generated.
-
- The .XPP driver does not interpret the command block or in any way participate in
- executing the command’s function. It simply conveys the command block, included in a
- higher-level format, to the server end of the session, and returns the command reply
- to the workstation-end client. The command reply consists of a four-byte command
- result and a variable size command reply block.
-
- UserWrite allows the workstation to convey blocks of data to the server. UserWrite
- is used to transfer a variable size block of data to the server end of the session
- and to receive a reply.
-
- The AFPCall function provides a mechanism for passing an AFP command to the server
- end of an open session and receiving a reply. The first byte of the AFPCall command
- buffer contains the code for the AFP command that is to be passed to the server for
- execution. Most AFP calls are implemented through a very simple one-to-one mapping
- that takes the call and makes an ASP command out of it.
-
- The AFPCall function can have one of four different, but very similar, formats.
-
- »Getting Server Status Information
-
- ASP provides a service to allow its workstation clients to obtain a block of service
- status information from a server without the need for opening a session. The GetStatus
- function returns a status block from the server identified by the indicated address.
- ASP does not impose any structure on the status block. This structure is defined by
- the protocol above ASP.
-
- »Attention Mechanism
-
- Attentions are defined in ASP as a way for the server to alert the workstation of
- some event or critical piece of information. The ASP OpenSession and AFPLogin calls
- include a pointer to an attention routine in their parameter blocks. This attention
- routine is called by the .XPP driver when it receives an attention from the server
- and also when the session is closing as described below.
-
- In addition, upon receiving an OpenSession call or AFPLogin call, the .XPP driver
- sets the first two bytes of the session control block (SCB) to zero. When the .XPP
- driver receives an attention, the first two bytes of the SCB are set to the attention
- bytes from the packet (which are always nonzero).
-
- Note: A higher-level language such as Pascal may not wish to have a low-level
- attention routine called. A Pascal program can poll the attention bytes,
- and if they are ever nonzero, the program will know that an attention
- has come in. (It would then set the attention bytes back to zero.)
- Of course, two or more attentions could be received between successive
- polls, and only the last one would be recorded.
-
- The .XPP driver also calls the attention routine when the session is closed by either
- the server, workstation, or ASP itself (if the ASP session times out). In these
- cases, the attention bytes in the SCB are unchanged.
-
- »The Attention Routine
-
- The attention routine is called at interrupt level and must observe interrupt conventions.
- Specifically, the interrupt routine can change registers A0 through A3 and D0 through
- D3 and it must not make any Memory Manager calls.
-
- It will be called with
-
- • D0 (word) equal to the SessRefnum for that session (see OpenSession
- Function)
- • D1 (word) equal to the attention bytes passed by the server (or zero
- if the session is closing)
-
- Return with an RTS (return from subroutine) to resume normal execution.
-
- The next section describes the calls that can be made to the .XPP driver.
-
- _______________________________________________________________________________
-
-
- æKY Calling…the….XPP…Driver
- æC »CALLING THE .XPP DRIVER AppleTalkManager
- _______________________________________________________________________________
-
- This section describes how to use the .XPP driver and how to call the .XPP driver
- routines from assembly language and Pascal.
-
- _______________________________________________________________________________
-
- »Using XPP
-
- The .XPP driver implements the workstation side of ASP and provides a mechanism for
- the workstation to send AppleTalk Filing Protocol (AFP) commands to the server.
-
- »Allocating Memory
-
- Every call to the .XPP driver requires the caller to pass in whatever memory is
- needed by the driver for the call, generally at the end of the queue element. When a
- session is opened, the memory required for maintenance of that session
- (that is, the Session Control Block) is also passed in.
-
- For standard Device Manager calls, a queue element of a specific size equal to IOQElSize
- is allocated. When issuing many calls to XPP, it is the caller’s responsibility to
- allocate a queue element that is large enough to accommodate the .XPP driver’s requirements
- for executing that call, as defined below. Once allocated, that memory can’t be
- modified until the call completes.
-
- »Opening the .XPP Driver
-
- To open the .XPP driver, issue a Device Manager Open call. (Refer to the Device
- Manager chapter.) The name of the .XPP driver is '.XPP'. The original Macintosh
- ROMs require that .XPP be opened only once. With new ROMs, the .XPP unit number can
- always be obtained through an Open call. With old ROMs only, the .XPP unit number
- must be hard coded to XPPUnitNum (40) since only one Open call can be issued to the
- driver.
-
- The .XPP driver cannot be opened unless AppleTalk is open. The application must
- ensure that the .MPP and .ATP drivers are opened, as described earlier in this chapter.
-
- The xppLoaded bit (bit 5) in the PortBUse byte in low memory indicates whether or not
- the .XPP driver is open.
-
- »Example
-
- The following is an example of the procedure an application might use to open the
- .XPP driver.
-
- ; Routine: OpenXPP
- ;
- ; Open the .XPP driver and return the driver refNum for it.
- ;
- ; Exit: D0 = error code (ccr's set)
- ; D1 = XPP driver refNum (if no errors)
- ;
- ; All other registers preserved
- ;
- xppUnitNum EQU 40 ;default XPP driver number
- xppTfRNum EQU -(xppUnitNum+1) ;default XPP driver refNum
-
- OpenXPP
- MOVE.L A0-A1/D2,-(SP) ;save registers
- MOVE ROM85,D0 ;check ROM type byte
- BPL.S @10 ;branch if >=128K ROMs
- BTST #xppLoadedBit,PortBUse ;is the XPP driver open already?
- BEQ.S @10 ;if not open, then branch to Open code
- MOVE #xppTfRNum,D1 ;else use this as driver refnum
- MOVEQ #0,D0 ;set noErr
- BRA.S @90 ;and exit
- ;
- ; XPP driver not open. Make an _Open call to it. If using a 128K
- ; ROM machine and the driver is already open, we will make another
- ; Open call to it just so we get the correct driver refNum.
- ;
- @10 SUB #ioQElSize,SP ;allocate temporary param block
- MOVE.L SP,A0 ;A0 -> param block
- LEA XPPName, A1 ;A1 -> XPP (ASP/AFP) driver name
- MOVE.L A1,ioFileName(A0) ;driver name into param block
- CLR.B ioPermssn(A0) ;clear permissions byte
- _Open
- MOVE ioRefNum(A0),D1 ;D1=driver refNum (invalid if error)
- ADD #ioQElSize,SP ;deallocate temp param block
- @90 MOVE.L (SP)+,A0-A1/D2 ;restore registers
- TST D0 ;error? (set ccr's)
- RTS
-
- XPPName DC.B 4 ;length of string
- DC.B '.XPP' ;driver name
-
- From Pascal, XPP can be opened through the OpenXPP call, which returns the driver’s
- reference number:
-
- FUNCTION OpenXPP (VAR xppRefnum: INTEGER) : OSErr;
-
- »Open Errors
-
- Errors returned when calling the Device Manager Open routine if the function does not
- execute properly include the following:
-
- • errors returned by System
- • portInUse is returned if the AppleTalk port is in use by a driver
- other than AppleTalk or if AppleTalk is not open.
-
- »Closing the .XPP Driver
-
- To close the .XPP driver, call the Device Manager Close routine.
-
- Warning: There is generally no reason to close the driver. Use this
- call sparingly, if at all. This call should generally be used
- only by system-level applications.
-
- »Close Errors
-
- Errors returned when calling the Device Manager Close routine if the function does
- not execute properly include the following:
-
- • errors returned by System
- • closeErr (new ROMs only) is returned if you try to close the driver
- and there are sessions active through that driver. When sessions are
- active, closeErr is returned and the driver remains open.
- • on old ROMs the driver is closed whether or not sessions are active
- and no error is returned. Results are unpredictable if sessions are
- still active.
-
- »Session Control Block
-
- The session control block (SCB) is a nonrelocatable block of data passed by the
- caller to XPP upon session opening. XPP reserves this block for use in maintaining an
- open session. The SCB size is defined by the constant scbMemSize. The SCB is a
- locked block, and as long as the session is open, the SCB cannot be modified in any
- way by the application. There is one SCB for each open session. This block can be
- reused once a CloseSess call is issued and completed for that session or when the
- session is indicated as closed.
-
- _______________________________________________________________________________
-
- »How to Access the .XPP Driver
-
- This section contains information for programmers using Pascal and assembly-language
- routines.
-
- All .XPP driver routines can be executed either synchronously (meaning that the
- application can’t continue until the routine is completed) or asynchronously
- (meaning that the application is free to perform other tasks while the routine is
- executing).
-
- XPP calls are made from Pascal in the same manner as MPP and ATP calls, with the
- exception that when making XPP calls the caller must set the XPP driver’s refnum.
- This refnum is returned in the XPPOpen call’s parameter block.
-
- A Pascal variant record has been defined for all XPP calls. This parameter block is
- detailed in the “.XPP Driver Parameter Block Record” section below. The first four
- fields (which are the same for all calls) are automatically filled in by the device
- manager. The csCode field is automatically filled in by Pascal, depending on which
- call is being made. The caller must, however, set the ioRefnum field to XPP’s reference
- number, as returned in the OpenXPP call. The ioVRefnum field is unused.
-
- Note that the parameter block is defined so as to be the maximum size used by any
- call. Different calls take different size parameter blocks, each call requiring a
- certain minimum size. Callers are free to abbreviate the parameter block where
- appropriate.
-
- »General
-
- With each routine, a list of the parameter block fields used by the call is also
- given. All routines are invoked by Device Manager Control calls with the csCode
- field equal to the code corresponding to the function being called. The number next
- to each field name indicates the byte offset of the field from the start of the
- parameter block pointed to by A0; only assembly-language programmers need to be
- concerned with it. An arrow next to each parameter name indicates whether it’s an
- input, output, or input/output parameter:
-
- Arrow Meaning
- <-- Parameter is passed
- <-- Parameter is returned
- <-> Parameter is passed and returned
-
- All Device Manager Control calls return an integer result code in the ioResult field.
- Each routine description lists all the applicable result codes, along with a short
- description of what the result code means. Refer to the section
- “XPP Driver Result Codes” for an alphabetical list of result codes returned by the
- .XPP driver.
-
- Each routine description includes a Pascal form of the call. Pascal calls to the
- .XPP Driver are of the form:
-
- FUNCTION XPPCall (paramBlock: XPPParmBlkPtr,async: BOOLEAN) : OSErr;
-
- XPPCall is the name of the routine.
-
- The parameter paramBlock points to the actual I/O queue element used in the
- _Control call, filled in by the caller with the parameters of the routine.
-
- The parameter async indicates whether or not the call should be made asynchronously.
- If async is TRUE, the call is executed asynchronously; otherwise the call is executed
- synchronously.
-
- The routine returns a result code of type OSErr.
-
- ».XPP Driver Parameter Block Record
-
- XPPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OSErr; {result code}
- cmdResult: LONGINT; {command result (ATP user bytes) [long]}
- ioVRefNum: INTEGER; {volume reference or drive number)
- ioRefNum: INTEGER; {driver reference number)
- csCode: INTEGER; {Call command code}
- CASE XPPPrmBlkType OF
- ASPAbortPrm:
- (abortSCBPtr: Ptr); {SCB pointer for AbortOS [long]}
- ASPSizeBlk:
- (aspMaxCmdSize: INTEGER; {for SPGetParms [word]
- aspQuantumSize: INTEGER; {for SPGetParms [word]}
- numSesss: INTEGER); {for SPGetParms [word]}
- XPPPrmBlk:
- (sessRefnum: INTEGER; {offset to session refnum [word]}
- aspTimeout: Byte; {timeout for ATP [byte]}
- aspRetry: Byte; {retry count for ATP [byte]}
- CASE XPPSubPrmType OF
- ASPOpenPrm:
- (serverAddr: AddrBlock; {server address block [longword]}
- scbPointer: Ptr; {SCB pointer [longword]}
- attnRoutine: Ptr); {attention routine pointer [long]}
- ASPSubPrm:
- (cbSize: INTEGER; {command block size [word]}
- cbPtr: Ptr; {command block pointer [long]}
- rbSize: INTEGER; {reply buffer size [word]}
- rbPtr: Ptr; {reply buffer pointer [long]}
- CASE XPPEndPrmType OF
- AFPLoginPrm:
- (afpAddrBlock: AddrBlock; {address block in}
- { AFPlogin [long]}
- afpSCBPtr: Ptr; {SCB pointer in }
- { AFPlogin [long]}
- afpAttnRoutine: Ptr); {attn routine pointer }
- { in AFPlogin}
- ASPEndPrm:
- (wdSize: INTEGER; {write data size [word]}
- wdPtr: Ptr; {write data pointer [long]}
- ccbStart: ARRAY[0..295] OF Byte))); {CCB memory }
- { for driver}
- {Write max size(CCB) = 296; all other calls = 150}
- END;
-
- _______________________________________________________________________________
-
- »AppleTalk Session Protocol Functions
-
- This section contains descriptions of the .XPP driver functions that you can call.
- Each function description shows the required parameter block fields, their offsets
- within the parameter block and a brief definition of the field. Possible result
- codes are also described.
-
- »Note on Result Codes
-
- An important distinction exists between the aspParamErr and aspSessClose result
- codes that may be returned by the .XPP driver.
-
- When the driver returns aspParamErr to a call that takes as an input a session reference
- number, the session reference number does not relate to a valid open session. There
- could be several reasons for this, such as the workstation or server end closed the
- session or the server end of the session died.
-
- The aspSessClosed result code indicates that even though the session reference number
- relates to a valid session, that particular session is in the process of closing down
- (although the session is not yet closed).
-
- FUNCTION ASPOpenSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always ASPOpenSess
- --> 28 sessRefnum word Session reference number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 31 aspRetry byte Number of retries
- --> 32 serverAddr long word Server socket address
- --> 36 scbPointer pointer Pointer to session control block
- --> 40 attnRoutine pointer Pointer to attention routine
-
- ASPOpenSession initiates (opens) a session between the workstation and a server. The
- required parameter block is shown above. A brief definition of the fields follows.
-
- SessRefnum is a unique number identifying the open session between the workstation
- and the server. The SessRefnum is returned when the function completes successfully
- and is used in all calls to identify the session.
-
- ASPTimeOut is the interval in seconds between retries of the open session request.
-
- ASPRetry is the number of retries that will be attempted.
-
- ServerAddr is the network identifier or address of the socket on which the server is
- listening.
-
- SCBPointer points to a nonrelocatable block of data for the session control block
- (SCB) that the .XPP driver reserves for use in maintaining an open session. The SCB
- size is defined by the constant scbMemSize. The SCB is a locked block and as long as
- the session is open, the SCB cannot be modified in any way by the application. There
- is one SCB for each open session. This block can be reused when a CloseSess call is
- issued and completed for that session, or when the session is indicated as closed
- through return of aspParamErr as the result of a call for that session.
-
- AttnRoutine is a pointer to a routine that is invoked if an attention from the server
- is received, or upon session closing. If this pointer is equal to zero, no attention
- routine will be invoked.
-
- Result codes aspNoMoreSess Driver cannot support another session
- aspParamErr Server returned bad (positive) error code
- aspNoServers No servers at that address, or the server
- did not respond to the request
- reqAborted OpenSess was aborted by an AbortOS
- aspBadVersNum Server cannot support the offered
- version number
- aspServerBusy Server cannot open another session
-
- Note: The number of sessions that the driver is capable of supporting
- depends on the machine that the driver is running on.
-
- FUNCTION ASPCloseSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always ASPCloseSession
- --> 28 sessRefnum word Session reference number
-
- ASPCloseSession closes the session identified by the sessRefnum returned in the
- ASPOpenSession call. ASPCloseSession aborts any calls that are active on the session,
- closes the session, and calls the attention routine, if any, with an attention code
- of zero (zero is invalid as a real attention code).
-
- Result codes aspParamErr Parameter error, indicates an invalid
- session reference number
- aspSessClosed Session already in process of closing
-
- FUNCTION ASPAbortOS (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always ASPAbortOS
- --> 28 abortSCBPointer pointer Pointer to session control block
-
- ASPAbortOS aborts a pending (not yet completed) ASPOpenSession call. The aborted
- ASPOpenSession call will return a reqAborted error.
-
- AbortSCBPointer points to the original SCB used in the the pending ASPOpenSession
- call.
-
- Result codes cbNotFound SCB not found, no outstanding open session
- to be aborted.
- Pointer did not point to an open session SCB.
-
- FUNCTION ASPGetParms (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
-
- Parameter block
- --> 26 csCode word Always ASPGetParms
- --> 28 aspMaxCmdSize word Maximum size of command block
- --> 30 aspQuantumSize word Maximum data size
- --> 32 numSesss word Number of sessions
-
- ASPGetParms returns three ASP parameters. This call does not require an open session.
-
- ASPMaxCmdSize is the maximum size of a command that can be sent to the server.
-
- ASPQuantumSize is the maximum size of data that can be transferred to the server in a
- Write request or from the server in a command reply.
-
- NumSess is the number of concurrent sessions supported by the driver.
-
- FUNCTION ASPCloseAll (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always ASPCloseAll
-
- ASPCloseAll closes every session that the driver has active, aborting all active
- requests and invoking the attention routines where provided. This call should be
- used carefully. ASPCloseAll can be used as a system level resource for making sure
- all sessions are closed prior to closing the driver.
-
- FUNCTION ASPUserWrite (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
-
- Parameter block
- --> 18 cmdResult long word ASP command result
- --> 26 csCode word Always UserWrite
- --> 28 sessRefnum word Session reference number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 32 cbSize word Command block size
- --> 34 cbPtr pointer Command block pointer
- <-> 38 rbSize word Reply buffer size and reply size
- --> 40 rbPtr pointer Reply buffer pointer
- <-> 44 wdSize word Write data size
- --> 46 wdPtr pointer Write data pointer
- --> 50 ccbStart record Start of memory for CCB
-
- ASPUserWrite transfers data on a session. ASPUserWrite is one of the two main calls
- that can be used to transfer data on an ASP session. The other call that performs a
- similar data transfer is ASPUserCommand described below. The ASPUserWrite command
- returns data in two different places. Four bytes of data are returned in the cmdResult
- field and a variable size reply buffer is also returned.
-
- CmdResult is four bytes of data returned by the server.
-
- SessRefnum is the session reference number returned in the ASPOpenSession call.
-
- ASPTimeOut is the interval in seconds between retries of the call. Notice that there
- is no aspRetry field (retries are infinite). The command will be retried at the
- prescribed interval until completion or the session is closed.
-
- CBSize is the size in bytes of the command data that is to be written on the session.
- The size of the command block must not exceed the value of aspMaxCmdSize returned by
- the ASPGetParms call. Note that this buffer is not the data to be written by the
- command but only the data of the command itself.
-
- CBPtr points to the command data.
-
- RBSize is passed and indicates the size of the reply buffer in bytes expected by the
- command. RBSize is also returned and indicates the size of the reply that was actually
- returned.
-
- RBPtr points to the reply buffer.
-
- WDSize is passed and indicates the size of the write data in bytes to be sent by the
- command. WDSize is also returned and indicates the size of the write data that was
- actually written.
-
- WDPointer points to the write data buffer.
-
- CCBStart is the start of the memory to be used by the .XPP driver for the command
- control block. The size of this block is equal to a maximum of 296 bytes. To determine
- the exact requirement, refer to the CCB Sizes section of this document.
-
- Result codes aspParamErr Invalid session number, session has
- been closed
- aspSizeErr Command block size is bigger than MaxCmdSize
- aspSessClosed Session is closing
- aspBufTooSmall Reply is bigger than response buffer;
- the buffer will be filled, data will
- be truncated
-
- FUNCTION ASPUserCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 18 cmdResult long word ASP command result
- --> 26 csCode word Always ASPUserCommand
- --> 28 sessRefnum word Session number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 32 cbSize word Command block size
- --> 34 cbPtr pointer Command block pointer
- <-> 38 rbSize word Reply buffer and reply size
- --> 40 rbPtr pointer Reply buffer pointer
- --> 50 ccbStart record Start of memory for CCB
-
- ASPUserCommand is used to send a command to the server on a session.
-
- SessRefnum is the session reference number returned in the ASPOpenSession call.
-
- ASPTimeOut is the interval in seconds between retries of the call. Notice that there
- is no aspRetry field (retries are infinite). The command will be retried at the
- prescribed interval until completion or the session is closed.
-
- CBSize is the size in bytes of the block of data that contains the command to be sent
- to the server on the session. The size of the command block must not exceed the
- value of aspMaxCmdSize returned by the ASPGetParms call.
-
- CBPointer points to the block of data containing the command that is to be sent to
- the server on the session.
-
- RBSize is passed and indicates the size of the reply buffer in bytes expected by the
- command. RBSize is also returned and indicates the size of the reply that was actually
- returned.
-
- RBPtr points to the reply buffer.
-
- CCBStart is the start of the memory to be used by the .XPP driver for the command
- control block. The size of this block is equal to a maximum of 150 bytes. To determine
- the exact requirement refer to the CCB Sizes section of this document.
-
- Result codes aspParamErr Invalid session number, session has
- been closed
- aspSizeErr Command block size is bigger than MaxCmdSize
- aspSessClosed Session is closing
- aspBufTooSmall Reply is bigger than response buffer;
- the buffer will be filled, data will
- be truncated
-
- FUNCTION ASPGetStatus (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always ASPGetStatus
- --> 30 aspTimeout byte Retry interval in seconds
- --> 31 aspRetry byte Number of retries
- --> 32 serverAddr long word Server socket address
- <-> 38 rbSize word Reply buffer and reply size
- --> 40 rbPtr pointer Reply buffer pointer
- --> 50 ccbStart record Start of memory for CCB
-
- ASPGetStatus returns server status. This call is also used as GetServerInfo at the
- AFP level. This call is unique in that it transfers data over the network without
- having a session open. This call does not pass any data but requests that server
- status be returned.
-
- ASPTimeOut is the interval in seconds between retries of the call.
-
- ASPRetry is the number of retries that will be attempted.
-
- ServerAddr is the network identifier or address of the socket on which the server is
- listening.
-
- RBSize is passed and indicates the size of the reply buffer in bytes expected by the
- command. RBSize is also returned and indicates the size of the reply that was actually
- returned.
-
- RBPtr points to the reply buffer.
-
- CCBStart is the start of the memory to be used by the .XPP driver for the command
- control block. The size of this block is equal to a maximum of 150 bytes. To determine
- the exact requirement refer to the CCB Sizes section of this document.
-
- Result codes aspBufTooSmall Reply is bigger than response buffer,
- or Replysize is bigger than ReplyBuffsize
- aspNoServer No response from server at address used
- in call
-
- _______________________________________________________________________________
-
- »AFP Implementation
-
- The AFPCall function (called AFPCommand in Pascal) passes a command to an AFP server.
- The first byte of the AFPCall command buffer (the AFP command byte) must contain a
- valid AFP command code.
-
- Note: Server information should be gotten through an ASPGetStatus call
- (described above). ASPGetStatus is equivalent to the AFPGetSrvrInfo.
- Making an AFP GetSrvrInfo call using AFPCommand results in an error.
-
- »Mapping AFP Commands
-
- Most AFP calls are implemented by XPP through a very simple one-to-one mapping of an
- AFP call to an ASP call without interpretation or verification of the data.
-
- The .XPP driver maps AFP command codes to ASP commands according to the following
- conventions:
-
- AFP Command Code Comment
-
- $00 Invalid AFP command
- $01–$BE (1–190) Mapped to UserCommand (with the exceptions
- listed below)
- $BF (191) Mapped to UserCommand (Reserved for developers;
- will never be used by Apple)
- $C0–$FD (192–253) Mapped to UserWrite
- $FE (254) Mapped to UserWrite (will never be used by Apple)
- $FF (255) Invalid AFP command
-
- The following AFP calls are exceptions to the above conventions:
-
- AFP Command (Code/Decimal) Comment
-
- getSrvrInfo (15) Mapped to ASPGetStatus (Use ASPGetStatus
- to make this call)
- login (18) Mapped to appropriate log-in dialog including
- ASPOpenSession call
- loginCont (19) Mapped to appropriate log-in dialog
- logout (20) Mapped to ASPCloseSession
- write (33) Mapped to ASPUserWrite
-
- The following AFP calls can pass or return more data than can fit in quantumSize
- bytes (eight ATP response packets) and may be broken up by XPP into multiple ASP
- calls.
-
- AFP Command (Code/Decimal) Comment
-
- read (27) Can return up to the number of bytes
- indicated in reqCount
- write (33) Can pass up to the number of bytes
- indicated in reqCount
-
- »AFPCall Function
-
- The AFPCall function can have one of the following command formats.
-
- • General
- • Login
- • AFPWrite
- • AFPRead
-
- »General Command Format
-
- FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 18 cmdResult long word AFP command result
- --> 26 csCode word Always AFPCall
- --> 28 sessRefnum word Session reference number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 32 cbSize word Command buffer size
- --> 34 cbPtr pointer Command buffer
- <-> 38 rbSize word Reply buffer size and reply size
- --> 40 rbPtr pointer Reply buffer pointer
- <-> 44 wdSize word Write data size
- --> 46 wdPtr pointer Write data pointer
- --> 50 ccbStart record Start of memory for CCB
-
- The general command format for the AFPCall function passes an AFP command to the
- server. This format is used for all AFP calls except AFPLogin, AFPRead, and AFPWrite.
- Note that from Pascal this call is referred to as AFPCommand.
-
- CmdResult is four bytes of data returned from the server containing an indication of
- the result of the AFP command.
-
- SessRefnum is the session reference number returned in the AFPLogin call.
-
- ASPTimeOut is the interval in seconds between retries of the call by the driver.
-
- CBSize is the size in bytes of the block of data that contains the command to be sent
- to the server on the session. The size of the command block must not exceed the value
- of aspMaxCmdSize returned by the ASPGetParms call.
-
- CBPtr points to start of the block of data (command block) containing the command
- that is to be sent to the server on the session. The first byte of the command block
- must contain the AFP command byte. Subsequent bytes in the command buffer contain
- the parameters associated with the command as defined in the AFP document.
-
- RBSize is passed and indicates the size of the reply buffer in bytes expected by the
- command. RBSize is also returned and indicates the size of the reply that was actually
- returned.
-
- RBPtr points to the reply buffer.
-
- WDSize is the size of data to be written to the server (only used if the command is
- one that is mapped to an ASPUserWrite).
-
- WDPtr points to the write data buffer (only used if the command is one that is mapped
- to an ASPUserWrite).
-
- CCBStart is the start of the memory to be used by the .XPP driver for the command
- control block. The size of this block is equal to a maximum of 296 bytes. To determine
- the exact requirement refer to the CCB Sizes section of this document.
-
- Result codes aspParamErr Invalid session number; session has
- been closed
- aspSizeErr Command block size is bigger than MaxCmdSize
- aspSessClosed Session is closing
- aspBufTooSmall Reply is bigger than response buffer or
- buffer will be filled, data will be truncated
- afpParmError AFP command block size is equal to zero.
- This error will also be returned if the
- command byte in the command block is equal
- to 0 or $FF (255) or GetSrvrStatus (15).
-
- »Login Command Format
-
- The AFP login command executes a series of AFP operations as defined in the AFP Draft
- Proposal. For further information, refer to the AFP document.
-
- FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
-
- Parameter block
- --> 18 cmdResult long word AFP command result
- --> 26 csCode word Always AFPCall
- --> 28 sessRefnum word Session reference number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 31 aspRetry byte Number of retries
- --> 32 cbSize word Command buffer size
- --> 34 cbPtr pointer Command buffer
- <-> 38 rbSize word Reply buffer size and reply size
- --> 40 rbPtr pointer Reply buffer pointer
- --> 44 afpAddrBlock long word Server address block
- <-> 48 afpSCBPtr pointer SCB pointer
- <-> 52 afpAttnRoutine pointer Attention routine pointer
- --> 50 ccbStart record Start of command control block
-
- CmdResult is four bytes of data returned from the server containing an indication of
- the result of the AFP command.
-
- SessRefnum is the session reference number (returned by the AFPLogin call).
-
- ASPTimeOut is the interval in seconds between retries of the call.
-
- ASPRetry is the number of retries that will be attempted.
-
- CBSize is the size in bytes of the block data that contains the command to be sent to
- the server on the session. The size of the command block must not exceed the value of
- aspMaxCmdSize returned by the ASPGetParms call.
-
- CBPtr points to the block of data (command block) containing the AFP login command
- that is to be sent to the server on the session. The first byte of the command block
- must be the AFP login command byte. Subsequent bytes in the command buffer contain
- the parameters associated with the command.
-
- RBSize is passed and indicates the size of the reply buffer in bytes expected by the
- command. RBSize is also returned and indicates the size of the reply that was actually
- returned.
-
- RBPtr points to the reply buffer.
-
- AFPServerAddr is the network identifier or address of the socket on which the server
- is listening.
-
- AFPSCBPointer points to a locked block of data for the session control block
- (SCB). The SCB size is defined by scbMemSize. The SCB is a locked block, and as long
- as the session is open, the SCB cannot be modified in any way by the application.
- There is one SCB for each open session.
-
- AFPAttnRoutine is a pointer to a routine that is invoked if an attention from the
- server is received. When afpAttnRoutine is equal to zero, no attention routine will
- be invoked.
-
- CCBStart is the start of the memory to be used by the .XPP driver for the command
- control block. The size of this block is equal to a maximum of 150 bytes. To determine
- the exact requirement refer to the CCB Sizes section later in this chapter.
-
- Note: In the parameter block, the afpSCBPointer and the afpAttnRoutine
- fields overlap with the start of the CCB and are modified by the call.
-
- Result codes aspSizeErr Command block size is bigger than MaxCmdSize
- aspBufTooSmall Reply is bigger than response buffer or
- buffer will be filled, data will be truncated
- aspNoServer Server not responding
- aspServerBusy Server cannot open another session
- aspBadVersNum Server cannot support the offered ASP
- version number
- aspNoMoreSess Driver cannot support another session.
-
- »AFPWrite Command Format
-
- The AFPWrite and AFPRead command formats allow the calling application to make AFP-level
- calls that read or write a data block that is larger than a single ASP-level call is
- capable of reading or writing. The maximum number of bytes of data that can be read
- or written at the ASP level is equal to quantumSize.
-
- FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 18 cmdResult long word AFP command result
- --> 26 csCode word Always AFPCall
- --> 28 sessRefnum word Session number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 32 cbSize word Command buffer size
- --> 34 cbPtr pointer Command buffer
- <-> 38 rbSize word Reply buffer size and reply size
- --> 40 rbPtr pointer Reply buffer pointer
- --> 44 wdSize word (used internally)
- <-> 46 wdPtr pointer Write data pointer (updated)
- --> 50 ccbStart record Start of memory for CCB
-
- CmdResult is four bytes of data returned from the server containing an indication of
- the result of the AFP command.
-
- SessRefnum is the session reference number returned in the AFPLogin call.
-
- ASPTimeOut is the interval in seconds between retries of the call.
-
- CBSize is the size in bytes of the block data that contains the command to be sent to
- the server on the session. The size of the command block must not exceed the value
- of aspMaxCmdSize returned by the aspGetParms call.
-
- CBPtr points to the block of data (see command block structure below) containing the
- AFP write command that is to be sent to the server on the session. The first byte of
- the Command Block must contain the AFP write command byte.
-
- RBSize is passed and indicates the size of the reply buffer in bytes expected by the
- command. RBSize is also returned and indicates the size of the reply that was actually
- returned.
-
- RBPtr points to the reply buffer.
-
- WDSize is used internally.
-
- Note: This command does not pass the write data size in the queue element
- but in the command buffer. XPP will look for the size in that buffer.
-
- WDPtr is a pointer to the block of data to be written. Note that this field will be
- updated by XPP as it proceeds and will always point to that section of the data which
- XPP is currently writing.
-
- CCBStart is the start of the memory to be used by the XPP driver for the command
- control block. The size of this block is equal to a maximum of 296 bytes. To determine
- the exact requirement refer to the CCB Sizes section later in this chapter.
-
- Command Block Structure: The AFP write command passes several arguments to XPP in
- the command buffer itself. The byte offsets are relative to the location pointed to
- by cbPtr.
-
- --> 0 cmdByte byte AFP call command byte
- --> 1 startEndFlag byte Start/end Flag
- <-> 4 rwOffset long word Offset within fork to write
- <-> 8 reqCount long word Requested count
-
- CmdByte is the AFP call command byte and must contain the AFP write command code.
-
- StartEndFlag is a one-bit flag (the high bit of the byte) indicating whether the
- rwOffset field is relative to the beginning or the end of the fork (all other bits
- are zero).
-
- 0 = relative to the beginning of the fork
- 1 = relative to the end of the fork
-
- RWOffset is the byte offset within the fork at which the write is to begin.
-
- ReqCount indicates the size of the data to be written and is returned as the actual
- size written.
-
- The rwOffset and reqCount fields are modified by XPP as the write proceeds and will
- always indicate the current value of these fields.
-
- The Pascal structure of the AFP command buffer follows:
-
- AFPCommandBlock = PACKED RECORD
- cmdByte: Byte;
- startEndFlag: Byte;
- forkRefNum: INTEGER; {used by server}
- rwOffset: LONGINT;
- reqCount: LONGINT;
- newLineFlag: Byte; {unused by write}
- newLineChar: CHAR; {unused by write}
- END;
-
- Result codes aspParamErr Invalid session number
- aspSizeErr Command block size is bigger than MaxCmdSize
- aspSessClosed Session is closing
- aspBufTooSmall Reply is bigger than response buffer
-
- »AFPRead Command Format
-
- The AFPWrite and AFPRead command formats allow the calling application to make AFP-level
- calls that read or write a data block that is larger than a single ASP-level call is
- capable of reading or writing. The maximum number of bytes of data that can be read
- or written at the ASP level is equal to quantumSize.
-
- FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 18 cmdResult long word ASP command result
- --> 26 csCode word Always AFPCall
- --> 28 sessRefnum word Session number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 32 cbSize word Command buffer size
- --> 34 cbPtr pointer Command buffer
- --> 38 rbSize word Used internally
- <-> 40 rbPtr pointer Reply buffer pointer (updated)
- --> 50 ccbStart record Start of memory for CCB
-
- CmdResult is four bytes of data returned from the server containing an indication of
- the result of the AFP command.
-
- SessRefnum is the session reference number returned in the AFPLogin call.
-
- ASPTimeOut is the interval in seconds between retries of the call.
-
- CBSize is the size in bytes of the block data that contains the command to be sent to
- the server on the session. The size of the command block must not exceed the value
- of aspMaxCmdSize returned by the GetParms call.
-
- CBPtr points to the block of data (command block) containing the AFP read command
- that is to be sent to the server on the session. The first byte of the command block
- must contain the AFP read command byte. The command block structure is shown below.
-
- RBSize is used internally.
-
- Note: This command does not pass the read size in the queue element but
- in the command buffer. XPP will look for the size in that buffer.
-
- RBPtr points to the reply buffer. Note that this field will be updated by XPP as it
- proceeds and will always point to that section of the buffer that XPP is currently
- reading into.
-
- CCBStart is the start of the memory to be used by the .XPP driver for the command
- control block. The size of this block is equal to a maximum of 150 bytes. To determine
- the exact requirement refer to The CCB Sizes section later in this chapter.
-
- Command Block Structure: The AFP read command passes several arguments to XPP in the
- command buffer itself. The byte offsets are relative to the location pointed to by
- cbPointer.
-
- --> 0 cmdByte byte AFP call command byte
- <-> 4 rwOffset long word Offset within fork to read
- <-> 8 reqCount long word Requested count
- --> 12 newLineFlag byte Newline Flag
- --> 13 newLineChar byte Newline Character
-
- CmdByte is the AFP call command byte and must contain the AFP read command code.
-
- RWOffset is the byte offset within the fork at which the read is to begin.
-
- ReqCount indicates the size of the read data buffer and is returned as the actual
- size read.
-
- The rwOffset and reqCount fields are modified by XPP as the read proceeds and will
- always indicate the current value of these fields.
-
- NewLineFlag is a one-bit flag (the high bit of the byte) indicating whether or not
- the read is to terminate at a specified character (all other bits are zero).
-
- 0 = no Newline Character is specified
- 1 = a Newline Character is specified
-
- NewLineChar is any character from $00 to $FF (inclusive) that, when encountered in
- reading the fork, causes the read operation to terminate.
-
- The Pascal structure of the AFPCommand follows:
-
- AFPCommandBlock = PACKED RECORD
- cmdByte: Byte;
- startEndFlag: Byte; {unused for read}
- forkRefNum: INTEGER; {used by server}
- rwOffset: LONGINT;
- reqCount: LONGINT;
- newLineFlag: Byte;
- newLineChar: CHAR;
- END;
-
- Result codes aspParamErr Invalid session number
- aspSizeErr Command block size is bigger than MaxCmdSize
- aspSessClosed Session is closing
- aspBufTooSmall Reply is bigger than response buffer
-
- _______________________________________________________________________________
-
- »CCB Sizes
-
- The .XPP driver uses the memory provided at the end of the UserWrite, UserCommand,
- and GetStatus functions parameter blocks as an internal command control block (CCB).
- Using the maximum block sizes specified in the call descriptions will provide adequate
- space for the call to execute successfully. However, this section is provided for
- developers who wish to minimize the amount of memory taken up by the CCB in the queue
- element.
-
- Specifically, this memory is used for building data structures to be used in making
- calls to the ATP driver. This includes parameter blocks and buffer data structures
- (BDS). The structure of the BDS is detailed in elsewhere in this chapter. The exact
- size of this memory depends on the size of the response expected, and, in the case of
- UserWrite, on the size of data to be written.
-
- In the UserCommand and GetStatus cases (along with all AFP calls which map to UserCommand),
- a BDS must be set up to hold the response information. The number of entries in this
- BDS is equal to the size of the response buffer divided by the maximum number of data
- bytes per ATP response packet (578), rounded up. As described in the ASP chapter in
- Inside AppleTalk, ASP must ask for an extra response in the case where the response
- buffer is an exact multiple of 578. Of course, no BDS can be larger than eight
- elements. XPP also needs bytes for the queue element to call ATP with, so the minimum
- size of a CCB, as a function of the response buffer size (rbSize) is
-
- bdsSize = MIN (((rbSize DIV 578) + 1),8) * bdsEntrySz
- ccbSize = ioQElSize + 4 + bdsSize
-
- With UserWrite (and AFP calls mapping to UserWrite), XPP must create an additional
- BDS and queue element to use in sending the write data to the server. Therefore the
- minimum size of a UserWrite CCB, as a function of the response buffer and write data
- sizes (rbSize and wdSize) is:
-
- wrBDSSize = MIN (((wdSize DIV 578) + 1),8) * bdsEntrySz
- wrCCBSize = (2 * ioQElSize) + 4 + bdsSize + wrBDSSize
-
- Note: BDSEntrySz is equal to 12; ioQelSize is equal to 50.
-
- _______________________________________________________________________________
-
- ».XPP Driver Result Codes
-
- Result Code Comment Returned by
-
- aspBadVersNum Server cannot support the offered version ASPOpenSession
- number. AFPCall (Login)
-
- aspBufTooSmall Reply is bigger than response buffer. ASPUserWrite
- Buffer will be filled, data may be ASPUserCommand
- truncated. ASPGetStatus
- AFPCall
-
- aspNoMoreSess Driver cannot support another session. ASPOpenSessION
- AFPCall (Login)
-
- aspNoServers No servers at that address. ASPGetStatus
- The server did not respond to the request. ASPOpenSession
- AFPCall (Login)
-
- aspParamErr Parameter error, server returned bad ASPOpenSession
- (positive) error code. ASPCloseSess
- Invalid Session Reference Number. ASPUserWrite
- ASPUserCommand
- AFPCall
-
- aspServerBusy Server cannot open another session. ASPOpenSession
- AFPCall (Login)
-
- aspSessClosed Session already in process of closing. ASPCloseSession
- ASPUserWrite
- ASPUserCommand
- AFPCall
-
- aspSizeErr Command block size is bigger than ASPUserWrite
- maxParamSize. ASPUserCommand
- AFPCall
-
- cbNotFound SCB not found, no outstanding ASPAbortOS
- open session to be aborted. Pointer did
- not point to an open session SCB.
-
- afpParmError AFP Command Block size is less than or AFPCall
- equal to zero. Command byte in the
- Command block is equal to 0 or $FF (255)
- or GetSrvrStatus (15).
-
- reqAborted Open session was aborted by an ASPOpenSession
- Abort Open Session. AFPCall (Login)
-
- _______________________________________________________________________________
-
-
- æKY Protocol…Handlers…and…Socket…Listeners
- æC »PROTOCOL HANDLERS AND SOCKET LISTENERS AppleTalkManager
- _______________________________________________________________________________
-
- This section describes how to write your own protocol handlers and socket listeners.
- If you’re only interested in using the default protocol handlers and socket listeners
- provided by the Pascal interface, you can skip this section. Protocol handlers and
- socket listeners must be written in assembly language because they’ll be called by
- the .MPP driver with parameters in various registers not directly accessible from
- Pascal.
-
- The .MPP and .ATP drivers have been designed to maximize overall throughput while
- minimizing code size. Two principal sources of loss of throughput are unnecessary
- buffer copying and inefficient mechanisms for dispatching (routing) packets between
- the various layers of the network protocol architecture. The AppleTalk Manager completely
- eliminates buffer copying by using simple, efficient dispatching mechanisms at two
- important points of the data reception path: protocol handlers and socket listeners.
- To write your own, you should understand the flow of control in this path.
-
- _______________________________________________________________________________
-
- »Data Reception in the AppleTalk Manager
-
- When the SCC detects an ALAP frame addressed to the particular node (or a broadcast
- frame), it interrupts the Macintosh’s MC68000. An interrupt handler built into the
- .MPP driver gets control and begins servicing the interrupt. Meanwhile, the frame’s
- ALAP header bytes are coming into the SCC’s data reception buffer; this is a three-byte
- FIFO buffer. The interrupt handler must remove these bytes from the SCC’s buffer to
- make room for the bytes right behind; for this purpose, MPP has an internal buffer,
- known as the Read Header Area (RHA), into which it places these three bytes.
-
- The third byte of the frame contains the ALAP protocol type field. If the most significant
- bit of this field is set (that is, ALAP protocol types 128 to 255), the frame is an
- ALAP control frame. Since ALAP control frames are only three bytes long (plus two CRC
- bytes), for such frames the interrupt handler simply confirms that the CRC bytes
- indicate an error-free frame and then performs the specified action.
-
- If, however, the frame being received is a data frame (that is, ALAP protocol types 1
- to 127), intended for a higher layer of the protocol architecture implemented on that
- Macintosh, this means that additional data bytes are coming right behind. The interrupt
- handler must immediately pass control to the protocol handler corresponding to the
- protocol type specified in the third byte of the ALAP frame for continued reception
- of the frame. To allow for such a dispatching mechanism, the ALAP code in MPP maintains
- a protocol table. This consists of a list of currently used ALAP protocol types with
- the memory addresses of their corresponding protocol handlers. To allow MPP to transfer
- control to a protocol handler you’ve written, you must make an appropriate entry in
- the protocol table with a valid ALAP protocol type and the memory address of your
- code module.
-
- To enter your protocol handler into the protocol table, issue the LAPOpenProtocol
- call from Pascal or an AttachPH call from assembly language. Thereafter, whenever an
- ALAP header with your ALAP protocol type is received, MPP will call your protocol
- handler. When you no longer wish to receive packets of that ALAP protocol type, call
- LAPCloseProtocol from Pascal or DetachPH from assembly language.
-
- Warning: Remember that ALAP protocol types 1 and 2 are reserved by DDP
- for the default protocol handler and that types 128 to 255 are
- used by ALAP for its control frames.
-
- A protocol handler is a piece of assembly-language code that controls the reception
- of AppleTalk packets of a given ALAP protocol type. More specifically, a protocol
- handler must carry out the reception of the rest of the frame following the ALAP
- header. The nature of a particular protocol handler depends on the characteristics of
- the protocol for which it was written. In the simplest case, the protocol handler
- simply reads the entire packet into an internal buffer. A more sophisticated protocol
- handler might read in the header of its protocol, and on the basis of information
- contained in it, decide where to put the rest of the packet’s data. In certain cases,
- the protocol handler might, after examining the header corresponding to its own
- protocol, in turn transfer control to a similar piece of code at the next-higher
- level of the protocol architecture (for example, in the case of DDP, its protocol
- handler must call the socket listener of the datagram’s destination socket).
-
- In this way, protocol handlers are used to allow “on the fly” decisions regarding the
- intended recipient of the packets’s data, and thus avoid buffer copying. By using
- protocol handlers and their counterparts in higher layers
- (for instance, socket listeners), data sent over the AppleTalk network is read directly
- from the network into the destination’s buffer.
-
- _______________________________________________________________________________
-
- »Writing Protocol Handlers
-
- When the .MPP driver calls your protocol handler, it has already read the first five
- bytes of the packet into the RHA. These are the three-byte ALAP header and the next
- two bytes of the packet. The two bytes following the header must contain the length
- in bytes of the data in the packet, including these two bytes themselves, but excluding
- the ALAP header.
-
- Note: Since ALAP packets can have at most 600 data bytes, only the lower
- ten bits of this length value are significant.
-
- After determining how many bytes to read and where to put them, the protocol handler
- must call one or both of two functions that perform all the low-level manipulation of
- the SCC required to read bytes from the network. ReadPacket can be called repeatedly
- to read in the packet piecemeal or ReadRest can be called to read the rest of the
- packet. Any number of ReadPacket calls can be used, as long as a ReadRest call is
- made to read the final piece of the packet. This is necessary because ReadRest restores
- state information and verifies that the hardware-generated CRC is correct. An error
- will be returned if the protocol handler attempts to use ReadPacket to read more
- bytes than remain in the packet.
-
- When MPP passes control to your protocol handler, it passes various parameters and
- pointers in the processor’s registers:
-
- Register(s) Contents
-
- A0-A1 SCC addresses used by MPP
- A2 Pointer to MPP’s local variables (discussed below)
- A3 Pointer to next free byte in RHA
- A4 Pointer to ReadPacket and ReadRest jump table
- D1 (word) Number of bytes left to read in packet
-
- These registers, with the exception of A3, must be preserved until ReadRest is called.
- A3 is used as an input parameter to ReadPacket and ReadRest, so its contents may be
- changed. D0, D2, and D3 are free for your use. In addition, register A5 has been
- saved by MPP and may be used by the protocol handler until ReadRest is called. When
- control returns to the protocol handler from ReadRest, MPP no longer needs the data
- in these registers. At that point, standard interrupt routine conventions apply and
- the protocol handler can freely use
- A0-A3 and D0-D3 (they’re restored by the interrupt handler).
-
- D1 contains the number of bytes left to be read in the packet as derived from the
- packet’s length field. A transmission error could corrupt the length field or some
- bytes in the packet might be lost, but this won’t be discovered until the end of the
- packet is reached and the CRC checked.
-
- When the protocol handler is first called, the first five bytes of the packet
- (ALAP destination node ID, source node ID, ALAP protocol type, and length) can be
- read from the RHA. Since A3 is pointing to the next free position in the RHA, these
- bytes can be read using negative offsets from A3. For instance, the ALAP source node
- ID is at –4(A3), the packet’s data length (given in D1) is also pointed to by –2(A3),
- and so on. Alternatively, they can be accessed as positive offsets from the top of
- the RHA. The effective address of the top of the RHA is toRHA(A2), so the following
- code could be used to obtain the ALAP type field:
-
- LEA toRHA(A2),A5 ;A5 points to top of RHA
- MOVE.B lapType(A5),D2 ;load D2 with type field
-
- These methods are valid only as long as SCC interrupts remain locked out (which they
- are when the protocol handler is first called). If the protocol handler lowers the
- interrupt level, another packet could arrive over the network and invalidate the
- contents of the RHA.
-
- •••Refer to Technical Note #201:•••
-
- You can call ReadPacket by jumping through the jump table in the following way:
-
- JSR (A4)
-
- On entry D3: number of bytes to be read (word)
- A3: pointer to a buffer to hold the bytes
- On exit D0: modified
- D1: number of bytes left to read in packet (word)
- D2: preserved
- D3: = 0 if requested number of bytes were read
- <> 0 if error
- A0-A2: preserved
- A3: pointer to one byte past the last byte read
-
- ReadPacket reads the number of bytes specified in D3 into the buffer pointed to by
- A3. The number of bytes remaining to be read in the packet is returned in D1. A3
- points to the byte following the last byte read.
-
- You can call ReadRest by jumping through the jump table in the following way:
-
- JSR 2(A4)
-
- On entry A3: pointer to a buffer to hold the bytes
- D3: size of the buffer (word)
- On exit D0-D1: modified
- D2: preserved
- D3: = 0 if packet was exactly the size of the buffer
- < 0 if packet was (–D3) bytes too large to fit in
- buffer and was truncated
- > 0 if D3 bytes weren't read (packet is smaller
- than buffer)
- A0-A2: preserved
- A3: pointer to one byte past the last byte read
-
- ReadRest reads the remaining bytes of the packet into the buffer whose size is given
- in D3 and whose location is pointed to by A3. The result of the operation is returned
- in D3.
-
- ReadRest can be called with D3 set to a buffer size greater than the packet size;
- ReadPacket cannot (it will return an error).
-
- Warning: Remember to always call ReadRest to read the last part of a
- packet; otherwise the system will eventually crash.
-
- If at any point before it has read the last byte of a packet, the protocol handler
- wants to discard the remaining data, it should terminate by calling ReadRest as
- follows:
-
- MOVEQ #0,D3 ;byte count of 0
- JSR 2(A4) ;call ReadRest
- RTS
-
- Or, equivalently:
-
- MOVEQ #0,D3 ;byte count of 0
- JMP 2(A4) ;JMP to ReadRest, not JSR
-
- In all other cases, the protocol handler should end with an RTS, even if errors were
- detected. If MPP returns an error from a ReadPacket call, the protocol handler must
- quit via an RTS without calling ReadRest at all (in this case it has already been
- called by MPP).
-
- The Z (Zero) condition code is set upon return from these routines to indicate the
- presence of errors (CRC, overrun, and so on). Zero bit set means no error was detected;
- a nonzero condition code implies an error of some kind.
-
- Up to 24 bytes of temporary storage are available in MPP’s RHA. When the protocol
- handler is called, 19 of these bytes are free for its use. It may read several bytes
- (at least four are suggested) into this area to empty the SCC’s buffer and buy some
- time for further processing.
-
- MPP’s globals include some variables that you may find useful. They’re allocated as a
- block of memory pointed to by the contents of the global variable ABusVars, but a
- protocol handler can access them by offsets from A2:
-
- Name Contents
-
- sysLAPAddr This node’s node ID (byte)
- toRHA Top of the Read Header Area (24 bytes)
- sysABridge Node ID of a bridge (byte)
- sysNetNum This node’s network number (word)
- vSCCEnable Status Register (SR) value to re-enable SCC interrupts (word)
-
- Warning: Under no circumstances should your protocol handler modify
- these variables. It can read them to find the node’s ID, its
- network number, and the node ID of a bridge on the AppleTalk internet.
-
- If, after reading the entire packet from the network and using the data in the RHA,
- the protocol handler needs to do extensive post-processing, it can load the value in
- vSCCEnable into the SR to enable interrupts. To allow your programs to run transparently
- on any Macintosh, use the value in vSCCEnable rather than directly manipulating the
- interrupt level by changing specific bits in the SR.
-
- Additional information, such as the driver’s version number or reference number and a
- pointer (or handle) to the driver itself, may be obtained from MPP’s device control
- entry. This can be found by dereferencing the handle in the unit table’s entry corresponding
- to unit number 9; for more information, see the section “The Structure of a Device
- Driver” in the Device Manager chapter.
-
- »Timing Considerations
-
- Once it’s been called by MPP, your protocol handler has complete responsibility for
- receiving the rest of the packet. The operation of your protocol handler is time-critical.
- Since it’s called just after MPP has emptied the SCC’s three-byte buffer, the protocol
- handler has approximately 95 microseconds (best case) before it must call ReadPacket
- or ReadRest. Failure to do so will result in an overrun of the SCC’s buffer and loss
- of packet information. If, within that time, the protocol handler can’t determine
- where to put the entire incoming packet, it should call ReadPacket to read at least
- four bytes into some private buffer (possibly the RHA). Doing this will again empty
- the SCC’s buffer and buy another 95 microseconds. You can do this as often as necessary,
- as long as the processing time between successive calls to ReadPacket doesn’t exceed
- 95 microseconds.
-
- _______________________________________________________________________________
-
- »Writing Socket Listeners
-
- A socket listener is a piece of assembly-language code that receives datagrams delivered
- by the DDP built-in protocol handler and delivers them to the client owning that
- socket.
-
- When a datagram (a packet with ALAP protocol type 1 or 2) is received by the ALAP,
- DDP’s built-in protocol handler is called. This handler reads the DDP header into the
- RHA, examines the destination socket number, and determines whether this socket is
- open by searching DDP’s socket table. This table lists the socket number and corresponding
- socket listener address for each open socket. If an entry is found matching the
- destination socket, the protocol handler immediately transfers control to the appropriate
- socket listener. (To allow DDP to recognize and branch to a socket listener you’ve
- written, call DDPOpenSocket from Pascal or OpenSkt from assembly language.)
-
- At this point, the registers are set up as follows:
-
- Register(s) Contents
-
- A0-A1 SCC addresses used by MPP
- A2 Pointer to MPP’s local variables (discussed above)
- A3 Pointer to next free byte in RHA
- A4 Pointer to ReadPacket and ReadRest jump table
- D0 This packet’s destination socket number (byte)
- D1 Number of bytes left to read in packet (word)
-
- The entire ALAP and DDP headers are in the RHA; these are the only bytes of the
- packet that have been read in from the SCC’s buffer. The socket listener can get the
- destination socket number from D0 to select a buffer into which the packet can be
- read. The listener then calls ReadPacket and ReadRest as described under “Writing
- Protocol Handlers” above. The timing considerations discussed in that section apply
- as well, as do the issues related to accessing the MPP local variables.
-
- The socket listener may examine the ALAP and DDP headers to extract the various
- fields relevant to its particular client’s needs. To do so, it must first examine the
- ALAP protocol type field (three bytes from the beginning of the RHA) to decide whether
- a short (ALAP protocol type=1) or long (ALAP protocol type=2) header has been received.
-
- A long DDP header containing a nonzero checksum field implies that the datagram was
- checksummed at the source. In this case, the listener can recalculate the checksum
- using the received datagram, and compare it with the checksum value. The following
- subroutine can be used for this purpose:
-
- DoChksum ;
- ; D1 (word) = number of bytes to checksum
- ; D3 (word) = current checksum
- ; A1 points to the bytes to checksum
- ;
- CLR.W D0 ;clear high byte
- SUBQ.W #1,D1 ;decrement count for DBRA
- Loop MOVE.B (A1)+,D0 ;read a byte into D0
- ADD.W D0,D3 ;accumulate checksum
- ROL.W #1,D3 ;rotate left one bit
- DBRA D1,Loop ;loop if more bytes
- RTS
-
- Note: D0 is modified by DoChksum.
-
- The checksum must be computed for all bytes starting with the DDP header byte following
- the checksum field up to the last data byte (not including the CRC bytes). The socket
- listener must start by first computing the checksum for the DDP header fields in the
- RHA. This is done as follows:
-
- CLR.W D3 ;set checksum to 0
- MOVEQ #ddpHSzLong-ddpDstNet,D1
- ;length of header part to checksum
- LEA toRHA+lapHdSz+ddpDstNet(A2),A1
- ;point to destination network number
- JSR DoChksum
- ; D3 = accumulated checksum of DDP header part
-
- The socket listener must now continue to set up D1 and A1 for each subsequent portion
- of the datagram, and call DoChksum for each. It must not alter the value in D3.
-
- The situation of the calculated checksum being equal to 0 requires special attention.
- For such packets, the source sends a value of –1 to distinguish them from unchecksummed
- packets. At the end of its checksum computation, the socket listener must examine the
- value in D3 to see if it’s 0. If so, it’s converted to –1 and compared with the
- received checksum to determine whether there was a checksum error:
-
- TST.W D3 ;is calculated value 0?
- BNE.S @1 ;no -- go and use it
- SUBQ.W #1,D3 ;it is 0; make it -1
- @1 CMP.W toRHA+lapHdSz+ddpChecksum(A2),D3
- BNE ChksumError
-
- _______________________________________________________________________________
-
-
- æKY Summary…of…the…AppleTalk…Manager
- æC »SUMMARY OF THE APPLETALK MANAGER AppleTalkManager
- _______________________________________________________________________________
-
- Constants
-
- CONST
- lapSize = 20; {ABusRecord size for ALAP}
- ddpSize = 26; {ABusRecord size for DDP}
- nbpSize = 26; {ABusRecord size for NBP}
- atpSize = 56; {ABusRecord size for ATP}
-
- _______________________________________________________________________________
-
- Data Types
-
- TYPE
- ABProtoType = (lapProto,ddpProto,nbpProto,atpProto);
- ABRecHandle = ^ABRecPtr;
- ABRecPtr = ^ABusRecord;
- ABusRecord =
- RECORD
- abOpcode: ABCallType; {type of call}
- abResult: INTEGER; {result code}
- abUserReference: LONGINT; {for your use}
- CASE ABProtoType OF
- lapProto:
- (lapAddress: LAPAdrBlock; {destination or source node ID}
- lapReqCount: INTEGER; {length of frame data or buffer size in }
- { bytes}
- lapActCount INTEGER; {number of frame data bytes actually }
- { received}
- lapDataPtr: Ptr); {pointer to frame data or pointer to }
- { buffer}
- ddpProto:
- (ddpType: Byte; {DDP protocol type}
- ddpSocket: Byte; {source or listening socket number}
- ddpAddress: AddrBlock; {destination or source socket address}
- ddpReqCount: INTEGER; {length of datagram data or buffer size }
- { in bytes}
- ddpActCount: INTEGER; {number of bytes actually received}
- ddpDataPtr: Ptr; {pointer to buffer}
- ddpNodeID: Byte); {original destination node ID}
- nbpProto:
- (nbpEntityPtr: EntityPtr; {pointer to entity name}
- nbpBufPtr: Ptr; {pointer to buffer}
- nbpBufSize: INTEGER; {buffer size in bytes}
- nbpDataField: INTEGER; {number of addresses or socket }
- { number}
- nbpAddress: AddrBlock; {socket address}
- nbpRetransmitInfo:RetransType); {retransmission information}
- atpProto:
- (atpSocket: Byte; {listening or responding socket number}
- atpAddress: AddrBlock; {destination or source socket address}
- atpReqCount: INTEGER; {request size or buffer size}
- atpDataPtr Ptr; {pointer to buffer}
- atpRspBDSPtr: BDSPtr; {pointer to response BDS}
- atpBitMap: BitMapType; {transaction bit map}
- atpTransID: INTEGER; {transaction ID}
- atpActCount: INTEGER; {number of bytes actually received}
- atpUserData: LONGINT; {user bytes}
- atpXO: BOOLEAN; {exactly-once flag}
- atpEOM: BOOLEAN; {end-of-message flag}
- atpTimeOut: Byte; {retry timeout interval in seconds}
- atpRetries: Byte; {maximum number of retries}
- atpNumBufs: Byte; {number of elements in response BDS or }
- { number of response packets sent}
- atpNumRsp: Byte; {number of response packets received or }
- { sequence number}
- atpBDSSize: Byte; {number of elements in response BDS}
- atpRspUData: LONGINT; {user bytes sent or received in }
- { transaction response}
- atpRspBuf: Ptr; {pointer to response message buffer}
- atpRspSize: INTEGER); {size of response message buffer}
- END;
-
- ABCallType = (tLAPRead,tLAPWrite,tDDPRead,tDDPWrite,tNBPLookup,tNBPConfirm,
- tNBPRegister,tATPSndRequest,tATPGetRequest,tATPSdRsp,tATPAddRsp,
- tATPRequest,tATPResponse);
-
- LAPAdrBlock = PACKED RECORD
- dstNodeID: Byte; {destination node ID}
- srcNodeID: Byte; {source node ID}
- lapProtType: ABByte {ALAP protocol type}
- END;
-
- ABByte = 1..127; {ALAP protocol type}
- AddrBlock = PACKED RECORD
- aNet: INTEGER; {network number}
- aNode: Byte; {node ID}
- aSocket: Byte {socket number}
- END;
-
- BDSPtr = ^BDSType;
- BDSType = ARRAY[0..7] OF BDSElement; {response BDS}
- BDSElement = RECORD
- buffSize: INTEGER; {buffer size in bytes}
- buffPtr: Ptr; {pointer to buffer}
- dataSize: INTEGER; {number of bytes actually received}
- userBytes: LONGINT {user bytes}
- END;
-
- BitMapType = PACKED ARRAY[0..7] OF BOOLEAN;
- EntityPtr = ^EntityName;
- EntityName = RECORD
- objStr: Str32; {object}
- typeStr: Str32; {type}
- zoneStr: Str32 {zone}
- END;
-
- Str32 = STRING[32];
- RetransType =
- PACKED RECORD
- retransInterval: Byte; {retransmit interval in 8-tick units}
- retransCount: Byte {total number of attempts}
- END;
-
- MPPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OSErr; {result code}
- ioNamePtr: StringPtr; {command result (ATP user bytes) [long]}
- ioVRefNum: INTEGER; {volume reference or drive number}
- ioRefNum: INTEGER; {driver reference number}
- csCode: INTEGER; {call command code AUTOMATICALLY SET}
-
- CASE MPPParmType OF
- LAPWriteParm:
- (filler0:INTEGER;
- wdsPointer:Ptr); {->Write Data Structure}
- AttachPHParm,DetachPHParm:
- (protType:Byte; {ALAP Protocol Type}
- filler1:Byte;
- handler:Ptr); {->protocol handler routine}
- OpenSktParm,CloseSktParm,WriteDDPParm:
- (socket:Byte; {socket number}
- checksumFlag:Byte; {checksum flag}
- listener:Ptr); {->socket listener routine}
- RegisterNameParm,LookupNameParm,ConfirmNameParm,RemoveNameParm:
- (interval:Byte; {retry interval}
- count:Byte; {retry count}
- entityPtr:Ptr; {->names table element or }
- { ->entity name}
- CASE MPPParmType OF
- RegisterNameParm:
- (verifyFlag:Byte; {set if verify needed}
- filler3:Byte);
- LookupNameParm:
- (retBuffPtr:Ptr; {->return buffer}
- retBuffSize:INTEGER; {return buffer size}
- maxToGet:INTEGER; {matches to get}
- numGotten:INTEGER); {matched gotten}
- ConfirmNameParm:
- (confirmAddr:AddrBlock; {->entity}
- newSocket:Byte; {socket number}
- filler4:Byte));
-
- SetSelfSendParm:
- (newSelfFlag:Byte; {self-send toggle flag}
- oldSelfFlag:Byte); {previous self-send state}
- KillNBPParm:
- (nKillQEl:Ptr); {ptr to Q element to cancel}
- END;
-
- ATPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OSErr; {result code}
- userData: LONGINT; {ATP user bytes [long]}
- reqTID: INTEGER; {request transaction ID}
- ioRefNum: INTEGER; {driver reference number
- csCode: INTEGER; {Call command code }
- { AUTOMATICALLY SET}
- atpSocket: Byte; {currBitMap or socket number}
- atpFlags: Byte; {control information}
- addrBlock: AddrBlock; {source/dest. socket address}
- reqLength: INTEGER; {request/response length}
- reqPointer: Ptr; {-> request/response data}
- bdsPointer: Ptr; {-> response BDS}
- CASE MPPParmType OF
- SendRequestParm,NSendRequestParm:
- (numOfBuffs:Byte; {numOfBuffs}
- timeOutVal:Byte; {timeout interval}
- numOfResps:Byte; {number responses actually received}
- retryCount:Byte; {number of retries}
- intBuff:INTEGER); {used internally for NSendRequest}
- SendResponseParm:
- (filler0:Byte; {number of responses being sent}
- bdsSize:Byte; {number of BDS elements}
- transID:INTEGER); {transaction ID}
- GetRequestParm:
- (bitMap:Byte; {bit map}
- filler1:Byte);
- AddResponseParm:
- (rspNum:Byte; {sequence number}
- filler2:Byte);
- KillSendReqParm,KillGetReqParm:
- (aKillQEl:Ptr); {ptr to Q element to cancel}
- END;
-
- XPPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OSErr; {result code}
- cmdResult: LONGINT; {command result (ATP user bytes) [long]}
- ioVRefNum: INTEGER; {volume reference or drive number)
- ioRefNum: INTEGER; {driver reference number)
- csCode: INTEGER; {Call command code}
- CASE XPPPrmBlkType OF
- ASPAbortPrm:
- (abortSCBPtr: Ptr); {SCB pointer for AbortOS [long]}
- ASPSizeBlk:
- (aspMaxCmdSize: INTEGER; {for SPGetParms [word]
- aspQuantumSize: INTEGER; {for SPGetParms [word]}
- numSesss: INTEGER); {for SPGetParms [word]}
- XPPPrmBlk:
- (sessRefnum: INTEGER; {offset to session refnum [word]}
- aspTimeout: Byte; {timeout for ATP [byte]}
- aspRetry: Byte; {retry count for ATP [byte]}
- CASE XPPSubPrmType OF
- ASPOpenPrm:
- (serverAddr: AddrBlock; {server address block [longword]}
- scbPointer: Ptr; {SCB pointer [longword]}
- attnRoutine: Ptr); {attention routine pointer [long]}
- ASPSubPrm:
- (cbSize: INTEGER; {command block size [word]}
- cbPtr: Ptr; {command block pointer [long]}
- rbSize: INTEGER; {reply buffer size [word]}
- rbPtr: Ptr; {reply buffer pointer [long]}
- CASE XPPEndPrmType OF
- AFPLoginPrm:
- (afpAddrBlock: AddrBlock; {address block in}
- { AFPlogin [long]}
- afpSCBPtr: Ptr; {SCB pointer in }
- { AFPlogin [long]}
- afpAttnRoutine: Ptr); {attn routine pointer }
- { in AFPlogin}
- ASPEndPrm:
- (wdSize: INTEGER; {write data size [word]}
- wdPtr: Ptr; {write data pointer [long]}
- ccbStart: ARRAY[0..295] OF Byte))); {CCB memory }
- { for driver}
- {Write max size(CCB) = 296; all other calls = 150}
- END;
-
- AFPCommandBlock = PACKED RECORD
- cmdByte: Byte;
- startEndFlag: Byte;
- forkRefNum: INTEGER; {used by server}
- rwOffset: LONGINT;
- reqCount: LONGINT;
- newLineFlag: Byte; {unused by write}
- newLineChar: CHAR; {unused by write}
- END;
-
- AFPCommandBlock = PACKED RECORD
- cmdByte: Byte;
- startEndFlag: Byte; {unused for read}
- forkRefNum: INTEGER; {used by server}
- rwOffset: LONGINT;
- reqCount: LONGINT;
- newLineFlag: Byt